std::mutex
is not copyable only because the standard says so. They could probably have written a std::mutex
that was copyable, but they decided not to.
As a guess, a non-copyable std::mutex
might be more efficient, safer, or easier to understand.
As an example, here is why it might be safer/easier to understand: What does it mean to copy a std::mutex
that is locked? I, personally, have no idea what the right answer is; I suspect that the right answer is "that is nonsense". There is no "answer of least surprise".
Instead of having a surprising answer in concurrency code, by blocking copy we avoid the question. People storing a mutex who want to copy have to decide themselves what they want it to do.
C++ will under some circumstances automatically generate a copy constructor. Under more circumstances it will let you do MyClass(MyClass const&)=default
and write one when you ask for it.
If your class contains a non-copyable class, it won't generate one, and you cannot ask for it. This is because the generated copy constructor basically copies its members; if you cannot copy a member, it cannot generate a copy constructor.
So mutex
cannot be copied because the standard says so.
If a struct or class contains a non-copyable member, the default copy constructor cannot be used. You have to write one yourself explicitly.
If your type needs to store a mutex
, one approach to prevent the headache of having to maintain a copy ctor that manually copies all of its other members is to stick your non-mutex
state into a sub-struct, and then use its default copy. Then you decide what to do with the mutex
during the copy, and your copy ctor (and assignment copy operator) remain simple.
struct bob_with_mutex {
sturct bob_simple_data {
int x, y, z;
std::vector<char> buff;
};
bob_simple_data data;
std::mutex m;
bob_with_mutex( bob_with_mutex const& o ):
data(o.data)
{}
bob_with_mutex& operator=( bob_with_mutex const& o )
{
data = o.data;
return *this;
}
};
the type bob
has a mixture of a mutex and some data. The data is stored in a sub-structure. The copy ctor of bob_with_mutex
cannot be defaulted, but it simply says "copy the data, and nothing else".
The copy of the bob
has its own mutex.