Search code examples
c++void-pointersstdthread

Convert std::thread pointed by void pointer to object std::thread instead of pointer to object


I was looking to an exercise I did, specifically a class "threads manager" which manage threads (omg really? lol) by storing them inside an array of "typedef void *HANDLE;" declared inside a struct GROUP.

So I already made it working, but I saw that I was converting the "HANDLE", so "void*", by "reinterpret_cast" conversion to "std::thread*".

After I saw that I worried: how and can I convert it directly to an std::thread object?

I did this code for example:

#include <iostream>
#include <thread>

typedef void *HANDLE;

class thread_obj {
    public:
        void operator()(int x){
            for(int i = 0x0; i < x; i++){
                std::cout << "i = " << i << std::endl;
            }
        }
};

int main(){

    std::thread thr(thread_obj(), 0x3);
    HANDLE test = &thr;

    std::thread *p_thr = reinterpret_cast<std::thread*>(test);

    p_thr->join();

    return 0x0;
}

This is the original code.

If instead I do:

std::thread p_thr = reinterpret_cast<std::thread&>(test);

or:

std::thread p_thr = *reinterpret_cast<std::thread*>(test);

or:

std::thread *temp = reinterpret_cast<std::thread*>(test);
std::thread p_thr = *temp;

I always get:

error: use of deleted function ‘std::thread::thread(std::thread&)’

On "reinterpret_cast" line for the first and second case, and on the following assignment line for the third.

Now I suppose the problem is with the copy constructor called. I searched a little and I opened the thread class and I found it:

thread(thread&) = delete;

So :/ searching a little I only found the solution on which you override the copy constructor. In this case I think a solution could be make a superclass an re-declare this deleted constructor, right? But this is just a waste of time :/

So is there a way to convert this "void*" to "std::thread" object, again to a "std::thread" object? If yes or no can you explain me in detail please?

Thank you so much have a nice day and coding :D


Solution

  • What you really need is

    std::thread& ref_thr = *reinterpret_cast<std::thread*>(test);
    //         ^ declare a reference to a std::thread
    

    and then you can use ref_thr just like you would use a normal object.

    As you've found, the copy constructor for std::thread is deleted, so if you actually want to create a thread object from test, then you need to move the casted object into new_thr like

    std::thread new_thr = std::move(*reinterpret_cast<std::thread*>(test));
    

    but this means that the object pointer to by test is no longer usable as it was moved into new_thr. This is why you want to use a reference, unless you actually want to move it.