1

As far as I understand, on Windows CRITICAL_SECTION can be used only as a non-recursive mutex. To get recursive mutex you have to use OpenMutex and friends.

However, AFAIU, Win32 Mutex cannot be used with condition variable (InitializeConditionVariable et al.)

Is there a way to use recursive mutex in conjunction with condition variable on Windows?

jotik
  • 17,044
  • 13
  • 58
  • 123
Martin Sustrik
  • 783
  • 10
  • 22
  • 1
    You understood wrong. Critical sections (as far as mutexes) **can** be used recursively. – valdo Oct 11 '12 at 07:19

2 Answers2

6

valdo's comment is right. CRITICAL_SECTION is recursive. Here's a quotation from MSDN: "After a thread has ownership of a critical section, it can make additional calls to EnterCriticalSection or TryEnterCriticalSection without blocking its execution." Problem solved.

Martin Sustrik
  • 783
  • 10
  • 22
-1

That just wouldn't make any sense. Semantically, the point of a condition variable is that you atomically release the lock when you wait -- thus allowing other threads to acquire the lock to do the thing you are waiting for. However, the "release" operation on a recursive mutex may not actually unlock it, so waiting after a release could deadlock. The fact that you want a way to do this strongly suggests something is wrong with your design or your understanding of condition variables.

Think about it -- what should happen when a function that holds a lock on the recursive mutex calls a function that acquires a second lock and then calls the sleep function? If the lock is released, the first function's logic will break since the object will be modified while it held a lock on it. If the lock is not released, the wait will deadlock since the thing it is waiting for can never happen because it holds the lock another thread would need to make it happen.

There is no sensible way to use a condition variable without knowing whether or not you have a lock on it already. And if you know whether or not you have a lock, there's no need for a recursive lock function. If you know you already have a lock, don't bother calling the lock function. If you know you don't already have a lock, the lock function will work fine even if it's not recursive.

David Schwartz
  • 179,497
  • 17
  • 214
  • 278
  • In my use case recursive access to the mutex happens only after waiting is finished. Thus there's no problem. – Martin Sustrik Oct 11 '12 at 12:08
  • Since you're keeping track of when you're using the mutex recursively and when you're not, you don't need a recursive mutex. When you're using it recursively, just don't bother calling the lock/unlock functions. – David Schwartz Oct 11 '12 at 12:31
  • I would have to store the state (recursive vs. non-recursive) somewhere. This storage itself would have to be resistant to simulataneous access by multiple threads. That would mean using atomics. Etc. Too complex. As noted above, CRITICAL_SECTION *is* recursive, so no problem. Thanks for help anyway! – Martin Sustrik Oct 11 '12 at 20:06
  • That storage is specific to the thread accessing the structure, so there's no risk of simultaneous access. – David Schwartz Oct 11 '12 at 23:24
  • (A thread is either in a code path that will, or might, block on the condition variable or it isn't. No consultation with other threads should be needed.) – David Schwartz Oct 11 '12 at 23:54
  • After finishing the wait operation you have to inform all the threads that mutex should work as recursive now. To do that you need to set the flag and at least execute a memory barrier. – Martin Sustrik Oct 12 '12 at 06:32
  • There would be no point in informing the threads of that. Any thread that wasn't going to lock the mutex recursively wouldn't need to know anyway. And any thread that could check if the mutex was to work as recursive or not could just as well check if it already held a lock on the mutex itself through its own unshared tracking. – David Schwartz Oct 12 '12 at 06:52