Is there a way to tell whether or not the current thread in C++11 holds a lock on a mutex? In particular I want to ensure that certain functions in a class are only called while the calling thread holds onto a lock (via std::lock_guard
, std::unique_lock
, or something similar) for the object, with the std::mutex
being a member variable.
To avoid repeated locking and unlocking while the object is being used extensively, the responsibility for locking the mutex
needs to be up to the caller, and cannot be in each individual function, and if the current thread does not have a lock on the mutex
when any of these functions are called, I want to throw an exception.
It seems that I can't just use std::try_lock
followed by an unlock as necessary because std::try_lock
's behavior is undefined if the current thread already holds the lock.
Mutex only locks a thread. It does not lock a resource. You can still access it via direct memory manipulation. So in that sense it is not safe (but on the other hand nothing can stop you from direct memory manipulation).
Use pthread_mutex_lock(3THR) to lock the mutex pointed to by mutex . When pthread_mutex_lock() returns, the mutex is locked and the calling thread is the owner. If the mutex is already locked and owned by another thread, the calling thread blocks until the mutex becomes available.
Mutexes are used to protect shared resources. If the mutex is already locked by another thread, the thread waits for the mutex to become available. The thread that has locked a mutex becomes its current owner and remains the owner until the same thread has unlocked it.
A recursive mutex can be locked repeatedly by the owner. The mutex does not become unlocked until the owner has called pthread_mutex_unlock() for each successful lock request that it has outstanding on the mutex. An errorcheck mutex checks for deadlock conditions that occur when a thread relocks an already held mutex.
The way I would recommend doing this is to have the functions that can only be called while holding the mutex take a reference to a std::unique_lock
or std::lock_guard
. In the case of unique_lock
you probably also want to assert that it actually holds the lock.
This will leverage the compiler to enforce your requirements.
Presumably these functions are internal / private to your class, and you have user-facing functions that acquire the lock and then call these ones. If so, having an additional argument won't pollute the user facing API.
Something along these lines:
// public
void A::public_function() {
std::lock_guard<std::mutex> l(m_mutex);
// ... do stuff
b(l);
// ... do more stuff
}
// private
void A::b(std::lock_guard const& l) {
// ... do stuff that requires holding the mutex
}
If you need to use unique_lock
instead, simply assert that l.owns_lock()
is true in your function (in case you want to throw an exception).
My experience with recursive mutexes is that they make it easy to not take your lock strategy and ownership as serious as it deserves. And that they can end up biting you later. See this post.
Just use a recursive mutex and lock/unlock in your code as you would do without the guarantee of an upper-level lock. Then provide that mutex
also to the calling code who can use it (or not).
Most importantly, if the upper layer does not lock, your code will still work perfectly, though maybe at a degraded speed. If the upper layer does lock, this will be not much more than a check if it owns the lock and an refcount increment/decrement, similar overhead to what you were planning to do anyway.
There is (currently) no interface defined in the C++ standard library that allows you to check if the mutex is locked and you are the owner.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With