I am creating a C++ library for both Linux (with PThreads) and Windows (with their built-in WinThreads) which can be attached to any program, and needs to have a function called when the thread is exiting, similar to how atexit works for processes.
I know of pthread_cleanup_push and pthread_cleanup_pop for pthreads, but these do not work for me since they are macros that add another lexical scope, whereas I want to declare this function the first time my library is called into, and then allow the program itself to run its own code however it needs to. I haven't found anything similar in Windows whatsoever.
Note that this doesn't mean I want an outside thread to be alerted when the thread stops, or even that I can change the way the thread will be exited, since that is controlled by the program itself, my library is just attached, along for the ride.
So the question is: What is the best way, in this instance, for me to have a function I've written called when the thread closes, in either Windows or Linux, when I have no control over how the thread is created or destroyed?
For example in main program:
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;
}
In library:
void callMeOnExit()
{
printf("Exiting Thread!\n");
}
I would want for callMeOnExit to be called when the thread reaches return NULL; in this case, as well as when the main thread reaches the return 0;. Wrapping pthread_exit would work for other cases, and could be a solution, but I'd like a better one if possible.
If anyone has any ideas on how I might be able to do this, that would be great!
So after a few code reviews, we were able to find a much more elegant way to do this in Linux, which matches both what Windows does with Fibers (as Neeraj points out) as well as what I expected to find when I started looking into this issue.
The key is that pthread_key_create takes in, as the second argument, a pointer to a destructor, which is called when any thread which has initialized this TLS data dies. I was already using TLS elsewhere per thread, but a simple store into TLS would get you this feature as well to ensure it was called.
Change this:
pthread_create(&ntid, NULL, threadFunc, &nVal);
into:
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));
Then Add:
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;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With