Hello,

 

I’ve recently been tasked with writing a Java-style cross-platform asynchronous task execution service in C++ on top of Boost Threads 1.37.  After implementing this service, my unit tests discovered some unexpected behavior (well, unexpected to me anyways) with the way that boost::condition_variable_any, boost::recursive_mutex, and boost::unique_lock interact.  I wanted to find out if this behavior is intentional or if it should be considered a bug.

 

Basically, the problem occurs when the same thread has multiple unique_lock objects associated with the same recursive_mutex, and then calls condition_variable_any::wait.  It appears that the condition variable only releases one of the recursive locks, and the mutex is still considered locked by the calling thread.  All of my other methods in the unit test that call notify_one or notify_all require acquiring a lock on the recursive_mutex to modify non-trivial shared state checked by the condition, so they deadlock.  Refactoring the code so that the thread never acquires more than one lock on the mutex in any call sequence fixes the deadlock, but I feel that requiring my code maintainers and API users to honor this restriction is excessively unfriendly.

 

This behavior is unexpected to me because the Java and C# implementations of conditions and recursive mutexes (including the implicit ones in Object synchronization) do not have this deadlock – the condition variable wait properly releases all locks that the thread holds rather than just one, and when the thread waits up and reacquires the lock, the recursive count is properly restored.  Is this a bug or is this intentional?  If it is intentional, then I most likely have misunderstood the appropriate use case for unique_lock or how condition variables work in Boost (the different use cases for the locks are not especially clear in the documentation) and would like to know how to accomplish what my code tried to do.

 

Greg Peele

Applied Research Associates, Inc.