Chapter 14. Threads and related objects


Mutex-protected objects
Transferrable mutex locks
Mutex-protected references
Mutex objects
Condition variable objects
Shared lock objects
Execution threads
Checking the results of an execution thread
Arguments to run() methods must be copy-constructible
Optional superclasses of thread-executing objects
Running a lambda inside a separate thread
Cleanup thread
Stick a fork() in it: you're done
Thread logging
Timer threads
Using mcguffins to cancel recurring tasks
Weak local thread objects
Local thread singleton objects
Thread worker pools
A simple worker pool thread
Notifying an event file descriptor
Notifying an event queue
Thread-safe semaphore queue
A fixed semaphore


x::mutex, x::cond, and x::sharedlock, are full fledged reference-counted objects that implement similar semantics as their C++ library equivalent, except that they are reference-counted objects. A mutex lock gets released when the thread that holds the last reference to a lock goes out of scope, which may not necessarily be the same thread that acquired the lock. The read-write lock is a reference-counted wrapper for std::shared_mutex.

These classes implement basic locking functionality. An additional set of templates create formal design patterns that force acquisition of an appropriate lock in order to gain access to a protected object. x::mpobj implements a basic design pattern that forces lock acquisition in order to access and underlying resource in a thread-safe manner. Forgetting to acquire a mutex lock, before accessing an object, is a common source of difficult bugs. x::mpobj enforces lock acquisition. Access to the object requires obtaining a lock structure that's typically short-lived, so this is not a reference-counted object. x::mpcobj supplements x::mpobj with a condition variable.

The mutex-protected objects get instantiated by constructing a lock object. The lock must exist in auto scope (on the stack), in order to enforce the underlying requirement that mutexes must be unlocked by the same execution thread that locked them. An x::mptobj adds additional support for transferring the logical mutex locked to a different execution thread.

x::mp is an alternative design pattern for a mutex-protected wrapper around a reference-counted object.

The next step up is the x::sipobj template that defines somewhat important objects, which demand proper locking rights from a std::shared_mutex, providing two levels of access to the underlying objects. Finally, the x::vipobj template defines very important objects, which extend mere somewhat important objects with a protocol for registering and invoking handlers that notify interested parties anytime the very important object gets changed.

See ??? for some additional notes on mutex objects.