Search code examples
c++multithreadingstdthread

Get std::thread's thread:id before it runs?


I'm trying to build a thread-safety layer on top of C++ 11's std::thread where each object is assigned to an owning thread, and certain calls can raise a hard error when they are used on the wrong thread. The owning thread is the only one that can transfer an object to another thread.

I have it all working, except that I can't find a way to get a thread's thread::id before it is actually running. And I need to attach the new thread's ID to the object before I hand it off.

If I use

std::thread newThread( [theObject]()
                       {
                           // use theObject here.
                       } );

The earliest point I can get the thread's ID is after the definition of the thread object, at which point the thread is already running.

I see there is a default constructor for std::thread, but I can't see a way to give it a function to run on the thread afterwards.

Is there a way to perform two-step construction on a thread, or control the thread's ID at time of creation?


Solution

  • Start each thread inactived by passing a unique std::promise parameter, get the thread id first ( thread id is used as a pass by reference parameter for the purpose) afterwards let it wait for the promise to be set by the thread manager. This will also remove the hassle of using a conditional variable.

    Edited Snippet

    class smart_thread {
    public:
        smart_thread(std::function<void(void)> task)
        {
            thread_ = std::thread([=]() {
                id_ = std::this_thread::get_id();
                // wait here till activated
                future_.get();
                if(active_) task();
            });
        }
    
        void activate()  {
            promise_.set_value();
            active_ = true;
        }
    
        ~smart_thread() {
            if(!active_) promise_.set_value();
            thread_.join();
        }    
    private:
        std::thread::id id_;
        std::atomic<bool> active_ = false;
        std::thread thread_;
        std::promise<void> promise_;
        std::future<void> future_ = promise_.get_future();
    };
    
    void main()
    {
        auto task = []() { std::cout << "Hello World\n"; };
        smart_thread thread(task); // start thread inactive mode
        thread.activate(); // activate thread
    }