将普通数据传递给 pthread void *

发布于 2024-11-05 14:00:28 字数 142 浏览 0 评论 0原文

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

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

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

The pthread functions take a void * argument. How can a plain struct, not a pointer be sent in?

I want to send in a non pointer struct to one pthread function.

Also I want to send a pointer to the void * function, how is this done? can any pointer be sent in to the void * function?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

听不够的曲调 2024-11-12 14:00:28

不可能;你必须发送一个指针。然而,void * 可以指向任何东西。如果您的结构变量名为 foo,您可以简单地将其作为 (void *) &foo 传递,并且在函数内部,您可以将其转换回例如 < code>struct Foo 与 struct Foo * fooPtr = (struct Foo *) param;struct Foo foo = *((struct Foo *) param);

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

Not possible; you have to send a pointer. However, a void * can point to anything. If your struct variable is called foo, you can simply pass it as (void *) &foo, and inside the function, you can cast it back into e.g. a struct Foo with struct Foo * fooPtr = (struct Foo *) param; or struct Foo foo = *((struct Foo *) param);.

Edit: As @forsvarir mentioned in the comment, foo must not be a local variable (unless the invoking function waits for the thread to complete). See @Gavin Lock's post.

一张白纸 2024-11-12 14:00:28

根据您的评论,您需要做这样的事情...

在您的主代码中:

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)该结构的新副本,以便每个线程都有自己的值副本。

Based on your comments you need to do something like this...

In your main code:

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); */
}

In your watchdog thread:

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

In your navigation thread:

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

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

You can't just do:

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

Because myStruct will get cleaned up... when PassSomeStuff returns. Taking the address (getting a pointer to it), doesn't copy the object.

Note:

  • ANY of your threads can clean up the structure by calling free, as long as you're sure that ALL of the threads are finished with it.
  • ALL of the threads (main, watchdog, navigation) are refering to the same instance of the structure (so if they're changing its contents you may need to protect it with locking). If this isn't the desired effect, then you would need to create (malloc) a new copy of the structure at each step, so that each thread has it's own copy of the values.
银河中√捞星星 2024-11-12 14:00:28

正如已经提到的,您必须传递一个指针。将 void* 视为无类型指针,因此您必须将其转换回线程函数内的正确类型。 (参见 Aasmund 的回答)

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

我所说的“传递所有权”的意思是,传递结构体消息的函数不得删除它,而线程函数必须在使用完该结构体后删除该结构体。

As already mentioned, you have to pass a pointer. Think of void* as an untyped pointer, so you have to cast it back to the correct type inside your thread function. (see Aasmund's answer)

As forsvarir mentions, you HAVE to make sure that the pointed-to struct is not destroyed before the thread uses it - safest way to do this is to new the struct on the heap and pass its address and ownership to the thread function.

What I mean by "passing ownership" is that the function that news the struct must not delete it, and the thread function must delete the struct once it is done with it.

空宴 2024-11-12 14:00:28

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

您可以使用的另一种方法是将 pthread 屏障放入 init 结构中,并等待它:

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);到它自己的自动存储。

This isn't a complete answer, but rather an alternative solution to the warnings others have offered about making sure the structure still exists when the new thread gets it. Certainly you can use malloc to obtain it, and give the new thread the responsibility for freeing it. In many ways this seems like the simplest and cheapest way (no synchronization required), but the synchronization is actually hidden inside malloc and free, and could be mildly expensive, especially since most thread-oriented allocators (ptmalloc and tcmalloc for example) incur additional costs when the thread freeing the memory is not the same as the thread that allocated it.

An different approach you can use is to put a pthread barrier inside your init structure, and wait on it:

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

And have the thread start function also call pthread_barrier_wait(arg->barrier); after copying the struct to its own automatic storage.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文