With GCC 4.8.2 (on Linux/Debian/Sid 64 bits) -or GCC 4.9 when available - in C++11- I have some mutex
std::mutex gmtx;
actually, it is a static
member in some class Foo
containing both alpha
and beta
methods below.
it is locked in alpha
like
void alpha(void) { std::lock_guard<std::mutex> g(gmtx); beta(void); // some other work }
and I want to check in beta
that indeed gmtx
is locked:
void beta(void) { assert (gmtx.is_locked()); // some real work }
(notice that is_locked
is only called inside assert
... It can be very inefficient or even sometimes inaccurate)
Of course, I have other functions calling beta
, e.g.
void gamma(void) { std::lock_guard<std::mutex> g(gmtx); beta(); // some other work }
but is_locked
does not exist.... How should I define it? (actually I would like to be sure that the mutex has been locked in the same thread by some [indirect] caller...)
(the reason I want to test that with assert
is that beta
could be called elsewhere)
I cannot use try_lock
(unless using recursive mutexes), because in the common case it would lock an already locked mutex... (locked in the same thread by a caller) and this is not only undefined behavior but blocks entirely.
I want to avoid recursive mutexes (more costly than plain mutexes) unless I really have to.
NB: The real program is a bit more complex. Actually, all the methods are inside a class which maintain a naming bi-directional relation on "items". So I have inside that class a map from items to names and another from names to items. beta
would be the internal method adding really a naming, and alpha
and gamma
would be the methods finding -or adding- an item by its name, or a name by its item.
PS: the real program is not yet released, but should become part of MELT - its future monitor; you can download it (alpha stage, very buggy) from here (a temporary location)
If the mutex isn't currently locked by any thread, the calling thread locks it (from this point, and until its member unlock is called, the thread owns the mutex ). If the mutex is currently locked by another thread, the function fails and returns false , without blocking (the calling thread continues its execution).
If you don't, then a typical mutex is held in process memory and will simply cease to exist along with anything that might have access to it when the process terminates.
A Mutex is a lock that we set before using a shared resource and release after using it. When the lock is set, no other thread can access the locked region of code.
Strictly speaking, the question was about checking the lockedness of std::mutex
directly. However, if encapsulating it in a new class is allowed, it's very easy to do so:
class mutex : public std::mutex { public: #ifndef NDEBUG void lock() { std::mutex::lock(); m_holder = std::this_thread::get_id(); } #endif // #ifndef NDEBUG #ifndef NDEBUG void unlock() { m_holder = std::thread::id(); std::mutex::unlock(); } #endif // #ifndef NDEBUG #ifndef NDEBUG /** * @return true iff the mutex is locked by the caller of this method. */ bool locked_by_caller() const { return m_holder == std::this_thread::get_id(); } #endif // #ifndef NDEBUG private: #ifndef NDEBUG std::atomic<std::thread::id> m_holder; #endif // #ifndef NDEBUG };
Note the following:
std::mutex
except possibly for construction/destruction (which is a non-issue for mutex objects).m_holder
member is only accessed between taking the mutex and releasing it. Thus the mutex itself serves as the mutex of m_holder
. With very weak assumptions on the type std::thread::id
, locked_by_caller
will work correctly.std::lock_guard
are templates, so they work well with this new class.std::unique_lock<L>
has owns_lock
member function (equivalent of is_locked
as you say).
std::mutex gmtx; std::unique_lock<std::mutex> glock(gmtx, std::defer_lock); void alpha(void) { std::lock_guard<decltype(glock)> g(glock); beta(void); // some other work } void beta(void) { assert(glock.owns_lock()); // or just assert(glock); // some real work }
EDIT: In this solution, all lock operations should be performed via unique_lock glock
not 'raw' mutex gmtx
. For example, alpha
member function is rewritten with lock_guard<unique_lock<mutex>>
(or simply lock_guard<decltype(glock)>
).
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