Class template acyclic_mutex
poet::acyclic_mutex — A mutex wrapper which automatically detects potential deadlocks due to an inconsistent mutex locking order (e.g. deadly embrace).
Synopsis
template<typename Mutex = boost::mutex, typename Key = std::string, typename KeyCompare = std::less<Key> > class acyclic_mutex : public acyclic_mutex_base { public: // types typedef Mutex mutex_type; typedef Key key_type; typedef KeyCompare key_compare; // construct/copy/destruct acyclic_mutex(); acyclic_mutex(const Key &); // public member functions boost::optional<Key> node_key() const; // Boost.Thread Lockable concept support void lock(); bool try_lock(); void unlock(); // Boost.Thread TimedLockable concept support template<typename Timeout> bool timed_lock(const Timeout &); // Boost.Thread SharedLockable concept support void lock_shared(); bool try_lock_shared(); template<typename Timeout> bool timed_lock_shared(const Timeout &); void unlock_shared(); void unlock_and_lock_shared(); // Boost.Thread UpgradeLockable concept support void lock_upgrade(); void unlock_upgrade(); void unlock_upgrade_and_lock(); void unlock_upgrade_and_lock_shared(); void unlock_and_lock_upgrade(); };
Description
The acyclic_mutex
class automatically tracks the
order in which all the program's acyclic_mutex
objects
are locked, and detects any potential deadlocks. It does so by
building up a graph in the mutex_grapher singleton
of the mutex locking order, which is checked to insure the locking
order remains consistent as the program executes.
An acyclic_mutex
will model the same mutex concepts (see Boost.Thread
version 1.35.0 or later)
modeled by its Mutex
template type. Thus, you may use any appropriate
lock type from Boost.Thread to lock an acyclic_mutex
(for example,
a boost::unique_lock
).
The Mutex
template type may be any of the mutex classes provided by
Boost.Thread (version 1.35.0 or later) or libpoet itself. It may also be
a foreign mutex classes, as long as it models one of the
mutex concepts defined in the Boost.Thread documentation, and you define
a specialization of mutex_properties for the
foreign mutex class. However, recursive SharedLockable
and recursive UpgradeLockable
mutexes are not currently supported, due to there being no known implementations.
The KeyCompare
template parameter must define a strict weak ordering
for the Key
type. Note, this is
only used to determine if two keys are equivalent or not, and is not taken
to imply any particular locking order requirement between mutexes with inequivalent
keys. acyclic_mutex
objects with equivalent keys share the same
vertex in the locking order graph built by mutex_grapher.
For production code, the tracking of mutex locking order may be disabled program-wide
at compile time by defining either NDEBUG
or ACYCLIC_MUTEX_NDEBUG
.
Example Code
See also
-
mutex_grapher: used by
acyclic_mutex
objects to build up a locking order graph, and test the locking order for potential deadlocks.
acyclic_mutex
public construct/copy/destruct
-
acyclic_mutex();
The default constructor creates a mutex with no key. This causes the mutex to be allocated its own vertex in the locking order graph. Default construction requires the least effort from the user, and minimizes the possibility of false positives, but also incurs the most overhead in the locking order graph of the
mutex_grapher
. If your program allocates many mutex objects, it may be worth coming up with a scheme for assigning keys to your mutexes. -
acyclic_mutex(const Key & key);
Creates a mutex with the specified key. All mutexes with equivalent (according to the
KeyCompare
ordering) keys will share the same vertex in the locking order graph. This limits the size of the locking order graph, and so can reduce overhead if your program creates many mutex objects. However, it does require additional effort from the programmer to group the mutexes by key in a way which will not produce false positives.
acyclic_mutex
public member functions
-
boost::optional<Key> node_key() const;
Returns the mutex's key (wrapped in a
boost::optional
). If the mutex was default constructed, it will have no key and an uninitializedboost::optional
is returned. Additionally, if mutex debugging has been disabled by definingNDEBUG
orACYCLIC_MUTEX_NDEBUG
, then this function will always return an uninitializedboost::optional
.