Kennedy
Kennedy

Reputation: 317

C++ multithreading - beginner query

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

Answers (3)

Solomon Slow
Solomon Slow

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

Galik
Galik

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

MikeMB
MikeMB

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

Related Questions