Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Ensuring that current thread holds a lock on a C++11 mutex

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.

like image 429
markt1964 Avatar asked Mar 03 '15 06:03

markt1964


People also ask

How does mutex know to 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).

How do I lock my mutex?

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.

What happens if you try to lock a locked mutex?

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.

How do you lock and unlock a mutex?

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.


2 Answers

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.

like image 161
Arvid Avatar answered Oct 06 '22 19:10

Arvid


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.

like image 32
KillianDS Avatar answered Oct 06 '22 20:10

KillianDS