Issue
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)
Solution
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)>
).
Answered By - yohjp Answer Checked By - Mildred Charles (WPSolving Admin)