Reputation: 317
I'm learning about multithreading in C++. I'm following a tutorial that gave this example for explaining the way to 'move' from one thread to another using the move semantics:
std::thread thread_1( func_1 );
std::thread thread_2 = std::move( thread_1 );
thread_1 = std::thread(func_2);
std::thread thread_3 = std::move(thread_2);
thread_1 = std::move(thread_3);
The last line thread_1 = std::move(thread_3);
was indicated as not being a proper way of doing it because(as I understood it):
'thread_1' and 'thread_3' are both existing threads which own some functions(thread_1 owns func_2 and thread_3 owns func_1) and you are supposed to manage their life-cycle with .detach() or .join();
That was the explanation given in the tutorial however that doesn't make sense to me 100%. Please help me better understand that explanation of why that line of code is not a proper way to transfer ownership between threads. Thank you!
Upvotes: 1
Views: 131
Reputation: 27115
Your question does not show much awareness of the difference between a std::thread
variable, a std::thread
value, and a thread. Those are three different things. Your three initialization and assignment statements move (or, attempting to move) std::thread
values from variable to variable.
When you move a std::thread
value, you actually are calling a function: This is a function call:
thread_1 = std::move(thread_3);
It's calling a std::thread
member function named
std::thread::operator= (std::thread&& other)
And, it does three things. It must first destroy (i.e., effectively call the destructor of) the value of thread_1
, then it copies the guts of the thread_3
value into thread_1
, and then finally it must effectively "zero out" the thread_3
variable.
That fails in the first step--destroying the old thread_1
value--because the thread already is running.
The thread is not the variable, and it is not the value of the variable. The thread is an object in the operating system kernel, and the value of the thread_1
variable is merely a handle to the operating system object.
One of the rules enforced by the std::thread
class is that it won't allow you to destroy the handle to a running thread unless you have previously called the detach()
method. The detach()
method just sets a flag that means, "trust me, I know what I'm doing, I don't need the handle anymore because I won't need to exert control over the running thread again."
Upvotes: 0
Reputation: 48605
I believe the point is you can not move a running thread onto a thread object that is already running a thread. If you do, the program will end by calling std::trerminate
.
See the reference here.
You can only move a running thread onto a thread object that has been default constructed (without a function) or that has previously been moved from, or has been joined/detached (leaving it empty).
Upvotes: 2
Reputation: 21126
Actually, the right side of the assignment (thread_3
) is irrelevant. You must not assign to an std::thread
object that is joinable (is a handle to an OS thread), otherwise std::terminate
is called:
http://en.cppreference.com/w/cpp/thread/thread/operator%3D
Upvotes: 1