4

As the title of the question says, why C++ threads (std::thread and pthread) are movable but not copiable? What consequences are there, if we do make it copiable?

Niall
  • 30,036
  • 10
  • 99
  • 142
james
  • 1,107
  • 14
  • 29
  • 5
    Well what would you expect it to do? Is it really sensible for it to spawn up a new thread, performing the same function *on all the same data* as the existing one? Any attempted usage would almost certainly be in error. – BoBTFish Jan 27 '16 at 12:14
  • 1
    Making something movable but not copyable is a way of making sure that there is only one unique instance of the object. The type `fstream` works the same way, you can move it but not copy it (which saves us from deciding if the copy should also create another file on the disk). – Bo Persson Jan 27 '16 at 12:28
  • thanks guys, is anyone willing to provide an "answer" so that I can close off this question? – james Jan 27 '16 at 12:30

2 Answers2

6

Regarding copying, consider the following snippet:

void foo();

std::thread first (foo);     
std::thread second = first; // (*)

When the line marked (*) takes place, presumably some of foo already executed. What would the expected behavior be, then? Execute foo from the start? Halt the thread, copy the registers and state, and rerun it from there?

In particular, given that function objects are now part of the standard, it's very easy to launch another thread that performs exactly the same operation as some earlier thread, by reusing the function object.

There's not much motivation to begin with for this, therefore.


Regarding moves, though, consider the following:

std::vector<std::thread> threads;

without move semantics, it would be problematic: when the vector needs to internally resize, how would it move its elements to another buffer? See more on this here.

Ami Tavory
  • 74,578
  • 11
  • 141
  • 185
2

If the thread objects are copyable, who is finally responsible for the single thread of execution associated with the thread objects? In particular, what would join() do for each of the thread objects?

There are several possible outcomes, but that is the problem, there are several possible outcomes with no real overlap that can be codified (standardised) as a general use case.

Hence, the most reasonable outcome is that 1 thread of execution is associated with at most 1 thread object.

That is not to say some shared state cannot be provided, it is just that the user then needs to take further action in this regard, such as using a std::shared_ptr.

Niall
  • 30,036
  • 10
  • 99
  • 142