Check if thread is a boost thread

2019-02-24 04:25发布

问题:

For purposes of thread local cleanup I need to create an assertion that checks if the current thread was created via boost::thread. How can I can check if this was the case? That is, how can I check if the current thread is handled by boost::thread?

I simply need this to do a cleanup of thread local storage when the thread exits. Boost's thread_local_ptr appears to only work if the thread itself is a boost thread.

Note that I'm not doing the check at cleanup time, but sometime during the life of the thread. Some function calls one of our API/callbacks (indirectly) causing me to allocate thread-local storage. Only boost threads are allowed to do this, so I need to detect at that moment if the thread is not a boost thread.


Refer to Destruction of static class members in Thread local storage for the problem of not having a generic cleanup handler. I answered that and realized pthread_clenaup_push won't actually work: it isn't called on a clean exit form the thread.


While I don't have answer to detect a boost thread the chosen answer does solve the root of my problem. Boost thread_specific_ptr's will call their cleanup in any pthread. It must have been something else causing it not to work for me, as an isolated test shows that it does work.

回答1:

The premise for your question is mistaken :) boost::thread_specific_ptr works even if the thread is not a boost thread. Think about it -- how would thread specific storage for the main thread work, seeing as it's impossible for it to be created by boost? I have used boost::thread_specific_ptr from the main thread fine, and although I haven't examined boost::thread_specific_ptr's implementation, the most obvious way of implementing it would work even for non-boost threads. Most operating systems let you get a unique ID number for the current thread, which you can then use as an index into a map/array/hashtable.

More likely you have a different bug that prevents the behavior you're expecting to see from happening. You should open a separate question with a small compilable code sample illustrating the unexpected behavior.



回答2:

You can't do this with a static assertion: That would mean you could detect it at compile time, and that's impossible.

Assuming you mean a runtime check though:

If you don't mix boost::thread with other methods, then the problem just goes away. Any libraries that are creating threads should already be dealing with their own threads automatically (or per a shutdown function the API documents that you must call).

Otherwise you can keep, for example, a container of all pthread_ts you create not using boost::thread and check if the thread is in the container when shutting down. If it's not in the container then it was created using boost::thread.

EDIT: Instead of trying to detect if it was created with boost::thread, have you considered setting up your application so that the API callback can only occur in threads created with boost::thread? This way you prevent the problem up front and eliminate the need for a check that, if it even exists, would be painful to implement.



回答3:

Each time a boost thread ends, all the Thread Specific Data gets cleaned. TSD is a pointer, calling delete p* at destruction/reset.

Optionally, instead of delete p*, a cleanup handler can get called for each item. That handler is specified on the TLS constructor, and you can use the cleanup function to do the one time cleaning.

#include <iostream>
#include <boost/thread/thread.hpp>
#include <boost/thread/tss.hpp>

void cleanup(int* _ignored) {
    std::cout << "TLS cleanup" << std::endl;
}

void thread_func() {
    boost::thread_specific_ptr<int> x(cleanup);
    x.reset((int*)1); // Force cleanup to be called on this thread

    std::cout << "Thread begin" << std::endl;
}

int main(int argc, char** argv) {
    boost::thread::thread t(thread_func);

    t.join();

    return 0;
}