title: calling a callback from a thread using function pointers
body: <p>c program compiler gcc</p>
  
  <p>I have 3 files. main.c stop_watch.h and stop_watch.c</p>
  
  <p>This program does work. I call start_stopwatch. And it will callback in main.c timeout_cb() after the time has expired. I also run this in a seperate thread, as I don't want to block in main, as I will have other code I need to run.</p>
  
  <p>1) The seconds in g_start_timer always gives rubbish. I thought I might have solved this by creating the structure on the heap. Is there anyway I can solve this. I was thinking of creating the seconds element on the heap. But think this is over kill</p>
  
  <p>2) This program works fine, but if I comment out the line in main printf("=== timeout_cb: %p\n", timeout_cb); it will stack dump.</p>
  
  <p>3) when is the best time to free the memory. I was freeing it in main. But I am worried if the memory is freed before the thread has finished. That could cause a very unexpected result. I am thinking I could use thread_join() as free the memory after this call. However, I would need to return the thead_id that is created in the stop_watch.c, is there a way to return the thread_id that is created in stop_watch.c</p>
  
  <p>Many thanks for any suggestions,</p>
  
  <p><strong>main.c</strong></p>
  
  <pre><code>/* main.c */
      #include &lt;pthread.h&gt;
      #include &lt;stdio.h&gt;
      #include &lt;stdlib.h&gt;
  
  #include "stop_watch.h"
  
  /* call this when the time expires */
  void timeout_cb()
  {
      printf("=== your time is up run some job here ===\n");
  }
  
  int main()
  {
      struct data_struct *g_data_struct =
          (struct data_struct*) calloc(1, sizeof(*g_data_struct));
  
      if(!g_data_struct)
      {
          printf("=== failed to allocate memory ===\n");
          return 0;
      }
  
      g_data_struct-&gt;seconds = 3;
      g_data_struct-&gt;func_ptr = timeout_cb;
  
      //  printf("=== timeout_cb: %p\n", timeout_cb);
  
      start_stopwatch(g_data_struct);
  
      // free(g_data_struct);
      printf("=== End of Program - all threads in ===\n");
  
      pthread_exit(NULL);
  
      return 0;
  }
  </code></pre>
  
  <p><strong>stop_watch.h</strong></p>
  
  <pre><code>/* stop_watch.h */
  struct data_struct
  {
      int seconds;
      void (*func_ptr)(void);
  };
  void start_stopwatch(struct data_struct *g_data_struct);
  </code></pre>
  
  <p><strong>stop_watch.c</strong></p>
  
  <pre><code>#include &lt;stdio.h&gt;
  #include &lt;pthread.h&gt;
  
  #include "stop_watch.h"
  
  static void* g_start_timer(void *args)
  {
      void (*function_pointer)();
  
      int seconds = ((struct data_struct*) args)-&gt;seconds;
      function_pointer = ((struct data_struct*) args)-&gt;func_ptr;
  
      printf("=== go to sleep for %d\n", seconds);
  
      sleep(seconds);
  
      (void) (*function_pointer)();
  
      pthread_exit(NULL);
  
      return 0;
  }
  
  void start_stopwatch(struct data_struct *g_data_struct)
  {
      pthread_t thread_id;
      int rc;
  
      int seconds = g_data_struct-&gt;seconds;
      printf("=== start_stopwatch(): %d\n", seconds);
  
      rc =  pthread_create(&amp;thread_id, NULL, g_start_timer, (void *) &amp;g_data_struct);
  
      if(rc)
          printf("=== Failed to create thread\n");
  }
  </code></pre>