将正常数据传递给pthread void *

时间:2011-05-04 09:59:03

标签: c pthreads

pthread函数采用void *参数。如何发送普通结构而不是指针?

我想将非指针结构发送到一个pthread函数。

另外我想发送一个指向void *函数的指针,这是怎么做到的?可以将任何指针发送到void *函数吗?

4 个答案:

答案 0 :(得分:8)

不可能;你必须发一个指针。但是,void *可以指向任何内容。如果您的struct变量被称为foo,您可以简单地将其作为(void *) &foo传递,并且在函数内部,您可以将其转换回例如struct Foo。一个struct Foo * fooPtr = (struct Foo *) param; struct Foo foo = *((struct Foo *) param);foo

编辑:正如评论中提到的@forsvarir一样,{{1}} 不能是一个局部变量(除非调用函数等待线程完成)。请参阅@Gavin Lock的帖子。

答案 1 :(得分:7)

根据您的评论,您需要做类似的事情......

在您的主要代码中:

void PassSomeStuff(struct TheStruct myStruct) {
    struct TheStruct *pStruct = malloc(sizeof(struct TheStruct));
    memcpy(pStruct, &myStruct, sizeof(struct TheStruct));

    /* Start the watchdog thread passing in the structure */
    pthread_create(/* other args */, &myWatchDogThreadFunc, pStruct); */
}

在你的看门狗线程中:

void *myWatchDogThreadFunc(void *pArgs) {
    struct TheStruct *pStruct = (struct TheStruct *)pArgs;

    /* use the struct */

    /* Pass Ownership to the navigation thread*/
    /* Start the navigation thread passing in the structure */
    pthread_create(/* other args */, &myNavigationThreadFunc, pStruct); 
}

在您的导航主题中:

void *myNavigationThreadFunc(void *pArgs) {
    struct TheStruct *pStruct = (struct TheStruct *)pArgs;
    /* use the struct */

    /* cleanup */
    free(pStruct);  /* or pass it to somebody else... */
}

你不能只做:

void PassSomeStuff(struct TheStruct myStruct) {
    pthread_create(/* other args */, &myStruct);
}

因为myStruct会在PassSomeStuff返回时被清除。获取地址(获取指针),不会复制对象。

注意:

  • 您的任何线程都可以通过调用free来清理结构,只要您确定所有线程都已完成它。
  • 所有线程(主要,看门狗,导航)都引用了相同的结构实例(因此,如果它们正在更改其内容,您可能需要通过锁定来保护它)。如果这不是预期的效果,那么您需要在每一步创建(malloc)结构的新副本,以便每个线程都拥有它自己的值副本。

答案 2 :(得分:3)

如前所述,你必须传递一个指针。将void *视为无类型指针,因此必须将其强制转换为线程函数内的正确类型。 (见Aasmund的回答)

正如forsvarir所提到的,你必须确保在线程使用它之前不会销毁指向的结构 - 最安全的方法是在堆上新建结构并将其地址和所有权传递给线程函数

我所说的“传递所有权”是指结构必须不删除它的函数,并且线程函数必须一旦完成就删除结构用它。

答案 3 :(得分:1)

这不是一个完整的答案,而是其他人提供的关于确保在新线程获得结构时仍然存在的警告的替代解决方案。当然,您可以使用malloc来获取它,并让新线程负责free它。在许多方面,这似乎是最简单和最便宜的方式(不需要同步),但同步实际上隐藏在mallocfree内,并且可能稍微昂贵,特别是因为大多数面向线程的分配器(例如ptmalloc和tcmalloc)当释放内存的线程与分配它的线程不同时会产生额外的成本。

您可以使用的另一种方法是在init结构中放置一个pthread屏障,然后等待它:

pthread_barrier_init(&init_struct.barrier, 0, 2);
pthread_create(&td, 0, start_func, &init_struct);
pthread_barrier_wait(&init_struct.barrier);

让线程启动函数在将结构复制到自己的自动存储器后也调用pthread_barrier_wait(arg->barrier);