вызов обратного вызова из потока с использованием указателей на функции - PullRequest
5 голосов
/ 25 февраля 2009

c программный компилятор gcc

У меня есть 3 файла. main.c stop_watch.h и stop_watch.c

Эта программа работает. Я звоню start_stopwatch. И он перезвонит в main.c timeout_cb () после истечения времени. Я также запускаю это в отдельном потоке, так как я не хочу блокировать в main, так как у меня будет другой код, который мне нужно запустить.

1) Секунды в g_start_timer всегда дают мусор. Я думал, что мог бы решить эту проблему, создав структуру в куче. Есть ли в любом случае, я могу решить это. Я думал о создании элемента секунд в куче. Но думаю, что все кончено

2) Эта программа работает нормально, но если я закомментирую строку в основном printf ("=== timeout_cb:% p \ n", timeout_cb); он будет складывать дамп.

3) когда лучшее время для освобождения памяти. Я освободил это в основном. Но я волнуюсь, если память освобождается до завершения потока. Это может привести к очень неожиданному результату. Я думаю, что мог бы использовать thread_join () как освободить память после этого вызова. Однако мне нужно будет вернуть thead_id, созданный в stop_watch.c, есть ли способ вернуть thread_id, созданный в stop_watch.c

Большое спасибо за любые предложения,

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");
}

1 Ответ

8 голосов
/ 25 февраля 2009

Строка в start_stopwatch():

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

должно быть:

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

В первом случае вы передаете «указатель на указатель», когда вы действительно просто хотите передать указатель в качестве аргумента потока.

Что касается того, когда освобождать данные, существует много вариантов. Если вы будете всегда передавать данные потока в выделенном блоке кучи, то процесс потока g_start_timer() может освободить его, когда завершит извлечение данных. Обратите внимание, что если вы сделаете это, то часть протокола для запуска потока состоит в том, что блок аргумента потока должен быть выделен в куче.

...