8

我正在为 Linux(带有 PThreads)和 Windows(带有内置 WinThreads)创建一个 C++ 库,它可以附加到任何程序,并且需要在线程退出时调用一个函数,类似于 atexit 的工作原理过程。

我知道 pthreads 的 pthread_cleanup_push 和 pthread_cleanup_pop ,但它们对我不起作用,因为它们是添加另一个词法范围的宏,而我想在第一次调用我的库时声明这个函数,然后允许程序本身运行它自己的代码,但它需要。我在 Windows 中没有发现任何类似的东西。

请注意,这并不意味着我希望在线程停止时提醒外部线程,甚至我可以更改线程退出的方式,因为这是由程序本身控制的,我的库只是附加的乘车。

所以问题是:在这种情况下,当我无法控制线程的创建或销毁方式时,在 Windows 或 Linux 中,当线程关闭时调用我编写的函数,最好的方法是什么? ?

例如在主程序中:

void* threadFunc(void* arg)
{
    printf("Hello world!\n");
    return NULL;
}

int main(int argc, char** argv)
{
    int        numThreads = 1;
    pid_t*     pids       = NULL;
    pids     = (pid_t*)     calloc(sizeof(pid_t), numThreads);

    pthread_create(&ntid, NULL, threadFunc, &nVal);
    pthreads[0] = ntid;

    pthread_join(pthreads[0], NULL);
    return 0;
}

在图书馆:

void callMeOnExit()
{
    printf("Exiting Thread!\n");
}

我希望在线程达到 return NULL 时调用 callMeOnExit;在这种情况下,以及当主线程到达时返回 0;。包装 pthread_exit 将适用于其他情况,并且可能是一种解决方案,但如果可能的话,我想要一个更好的解决方案。

如果有人对我如何能够做到这一点有任何想法,那就太好了!

4

4 回答 4

7

因此,经过几次代码审查后,我们能够在 Linux 中找到一种更优雅的方式来执行此操作,它既符合 Windows 对 Fibers 所做的(正如 Neeraj 指出的那样),也符合我开始研究时期望找到的内容这个问题。

关键是pthread_key_create作为第二个参数接受一个指向析构函数的指针,当任何已初始化此 TLS 数据的线程死亡时调用该析构函数。我已经在每个线程的其他地方使用了 TLS,但是一个简单的存储到 TLS 中也可以获得这个功能,以确保它被调用。

于 2012-05-22T19:31:23.257 回答
4

改变这个:

pthread_create(&ntid, NULL, threadFunc, &nVal);

进入:

struct exitInformData
{
   void* (CB*)(void*);
   void* data;
   exitInformData(void* (cp*)(void*), void* dp): CB(cp) data(dp) {}
};
pthread_create(&ntid, NULL, exitInform, new exitInformData(&threadFunc, &nVal));

然后加:

void* exitInform(void* data)
{
    exitInformData* ei = reinterpret_cast<exitInformData*>(data);

    void* r = (ei.CB)(ei.data);   // Calls the function you want.
    callMeOnExit();               // Calls the exit notification.
    delete ei;
    return r;
}
于 2012-04-30T23:14:32.683 回答
3

对于 Windows,您可以尝试Fls Callbacks。它们的 FLS 系统可用于为每个线程分配(忽略“光纤”部分,每个线程包含一根光纤)存储。您获得此回调以释放存储空间,但也可以在回调中执行其他操作。

于 2012-05-05T17:43:14.220 回答
0

我发现已经被问过了,尽管当时给出的解决方案可能与您想要的不同......

另一个想法可能是简单地从 pthread_t 类/结构扩展,并覆盖 pthread_exit 调用以根据需要调用另一个函数,然后调用超类 pthread_exit

于 2012-04-30T22:06:12.113 回答