views:

868

answers:

1

Hello,

c program compiler gcc

I have 3 files. main.c stop_watch.h and stop_watch.c

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.

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

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.

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

Many thanks for any suggestions,

main.c

/* main.c */
    #include <pthread.h>
    #include <stdio.h>
    #include <stdlib.h>

#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->seconds = 3;
    g_data_struct->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;
}

stop_watch.h

/* stop_watch.h */
struct data_struct
{
    int seconds;
    void (*func_ptr)(void);
};
void start_stopwatch(struct data_struct *g_data_struct);

stop_watch.c

#include <stdio.h>
#include <pthread.h>

#include "stop_watch.h"

static void* g_start_timer(void *args)
{
    void (*function_pointer)();

    int seconds = ((struct data_struct*) args)->seconds;
    function_pointer = ((struct data_struct*) args)->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->seconds;
    printf("=== start_stopwatch(): %d\n", seconds);

    rc =  pthread_create(&thread_id, NULL, g_start_timer, (void *) &g_data_struct);

    if(rc)
        printf("=== Failed to create thread\n");
}
+3  A: 

The line in start_stopwatch():

rc =  pthread_create(&thread_id, NULL, g_start_timer, (void *) &g_data_struct);

should be:

rc =  pthread_create(&thread_id, NULL, g_start_timer, (void *) g_data_struct);

In the first case, you're passing a "pointer to a pointer" when you really just want to pass the pointer as the thread argument.

As far as when to free the data, there are many options. If you will always pass the thread data in a heap allocated block, then the g_start_timer() thread proc can free it when it's finished pulling the data out. Note that if you do this, then part of the protocol for starting the thread is that the thread argument block must be heap allocated.

Michael Burr