
Howard Hinnant wrote:
The "mixed thread safe" semantics I find interesting and a little worrisome. Having some functionality thread safe and some not could be seen as confusing.
"Mixed thread safe" is the way of the future. :-) Really. One needn't be confused by it. For starters, it's the default thread safety level for all standard types unless specified otherwise. Having some non-const methods be thread safe is also not that uncommon. A lock-free queue for example might offer thread safety for push and pop, but not for operator=. Only atomic types have a thread safe operator=, and atomicity for UDTs comes at a cost that is rarely justified. To get back to std::thread, the reason we want some of its operations to be thread safe is because we have a specific use case where the usual "the user needs to use a mutex" doesn't work. In particular, we want, given a std::thread X, thread A (or threads A1...An) to be able to join it and thread B to be able to cancel it, unblocking A. This can't be achieved by a simple user-level mutex protection because it will deadlock. Thread A will lock the mutex protecting X, join and block with the mutex locked. Thread B will attempt to acquire the mutex in order to invoke cancel and also block. Unless the target thread exits by itself, A and B will wait forever. Given that, we also want to not penalize the non-shared case by introducing more synchronization than needed. The semantics I outlined take care of both. If we make cancel() const, we can now state that shared_ptr<const thread> is a safe and useful solution for the sharing use case. I've no opinion on detach at the moment.