1

When I write multi-thread algorithms I find for some methods useful to have expectation about the state of the mutex. For some is it already locked, for some that it is not.

I come up with approach how to assert if the mutex has to be locked already:

ASSERT(!mutex.try_lock_shared()); // assert if the mutex is not uniquely locked

ASSERT(!mutex.try_lock()); // assert if the mutex is not at least shared locked

The question is how I could make assert that checks that the mutex is not locked ... from the current thread. For example if I do this

     if (mutex.try_lock()) {
        mutex.unlock();
     } else {
        ASSERT(false); // the mutex is locked
     }

it obviously fails from time to time just because some other thread has it locked.

gsf
  • 6,612
  • 7
  • 35
  • 64
  • 1
    "I am writhing very complex multi-thread algorithm with a lot of methods calling each other." - the best advice I can give here is: make it simpler. Just break it down to higher level steps so that you mentally who is responsible for the locking. Recursive mutexes are almost always a code smell. Like shared pointers, they are overused instead of thinking your design through to make it simple. – sehe Mar 26 '15 at 23:26
  • "Very complex" is the state that I achieved after I did all of these. I am not sure why everybody assumes that what I am asking is some how related to reentrant mutexes, when I explicitly asked for shared_mutex. What I want is as every good developer does, when I specify a method expectations, instead of comment I to be able to add an assert that makes it clear faster if something breaks the protocol. – gsf Mar 27 '15 at 15:39
  • I got that. It's just that when you are unable to explain - in what way - your specific application is complex, this leads me to think there's might be a bit of a design debt. Otherwise, I don't see how it is constructive/relevant to even mention this supposed complexity in the question. If you don't want this to have anything to do with that, you might just remove it from the question – sehe Mar 27 '15 at 16:11
  • Not sure why you would find it harmful to have, but I get rid of it since you are right it also does not contribute. – gsf Mar 27 '15 at 21:59
  • Just code your own mutexes that have precisely the behavior you want. You can implement them using regular mutexes to protect their internal state. For example, your "lock" function can first lock a regular mutex and then set a "who holds this lock" variable to the current thread's identifier. That makes the assertions work. – David Schwartz Mar 27 '15 at 22:29
  • Another reason to have this capability is to help test situations where the activities in the thread, within the locked region, take longer than expected and that this unexpected delay does not cause timeouts, unresponsiveness, etc. By adding a call to sleep only when the lock is actually taken, not every time a recursive lock could be locked, you don't horribly slow down your testing system. – Jason Harrison Oct 27 '15 at 19:16

1 Answers1

0

boost has recursive and non-recursive mutexes. If a function is reentrant, use a recursive mutex. Then you need not worry whether the current thread has already locked it.

Tim Brauer
  • 35
  • 5
  • I do not want to reenter in the mutex. Having the mutex locked will indicate an error. I would like to be signalled as soon as possible that I am having a mistake in the logic. – gsf Mar 26 '15 at 19:53
  • Try using a recursive mutex with a flag. The recursive mutex will allow you to lock multiple times on the same thread. The flag will denote whether it's been locked previously. Something like: `boost::recursive_mutex::scoped_lock l(mtx_); if (flag_) { // handle error } flag_ = true; ...` – Tim Brauer Mar 27 '15 at 10:50