Boost C++ Libraries: Ticket #706: Possible problem with condition releasing https://svn.boost.org/trac10/ticket/706 <pre class="wiki">I think this is a bug but since I have only just started using the threads library it could be a misunderstanding on my part. Since the actual application is quite complex I've created an imaginary scenario that shows the problem. Scenario: A single 'throttle' manager that only lets three threads at a time perform some work. When a thread wants to work it must successfully addRef and when it has finished it releases. Problem: If all available 'slots' are used I am using a condition in the addRef to wait for a release before continuing. Therefore I would expect that after the wait I can successfully assert that a slot is available. However, sometimes this does not appear to be true and I can only assume that sometimes the condition is not working properly. Work around: In CThrottle::release remove the 'unlock' so that the notify_one occurs while the method still has a lock on the m_mutexChangeState. Have I misunderstood how condition is supposed to work? Thanks, Dave. The code: #include &lt;boost\thread\thread.hpp&gt; #include &lt;boost\thread\recursive_mutex.hpp&gt; #include &lt;boost/thread/condition.hpp&gt; #include &lt;boost/shared_ptr.hpp&gt; #include &lt;windows.h&gt; #include &lt;crtdbg.h&gt; #include &lt;vector&gt; class CThrottle { int m_nThrottle; public: CThrottle() : m_nThrottle(0) {} void addRef() { boost::mutex::scoped_lock lockIncrement ( m_mutexIncrement ); boost::recursive_mutex::scoped_lock lockChangeState( m_mutexChangeState ); if ( !isAllowed() ) m_condition.wait( lockChangeState ); _ASSERT( isAllowed() ); // PROBLEM ++m_nThrottle; } void release() { boost::recursive_mutex::scoped_lock lockChangeState( m_mutexChangeState ); --m_nThrottle; lockChangeState.unlock(); m_condition.notify_one(); } bool isAllowed() { boost::recursive_mutex::scoped_lock lockChangeState( m_mutexChangeState ); return m_nThrottle &lt; 3; } private: boost::mutex m_mutexIncrement; boost::recursive_mutex m_mutexChangeState; boost::condition m_condition; }; class CTestThread { public: CTestThread( CThrottle * pThrottle ) : m_pThrottle( pThrottle ) {} void operator()() { m_pThrottle-&gt;addRef(); std::cout &lt;&lt; "Do something\n"; m_pThrottle-&gt;release(); } CThrottle * m_pThrottle; }; typedef boost::shared_ptr&lt;CTestThread&gt; _TestThreadPtr; int main(int argc, _TCHAR* argv[]) { CThrottle * pThrottle = new CThrottle(); boost::thread_group groupThreads; std::vector&lt;_TestThreadPtr&gt; list; for( int n=0; n &lt; 10000; ++n ) { _TestThreadPtr ptrTest( new CTestThread ( pThrottle ) ); groupThreads.create_thread( *ptrTest.get() ); list.push_back( ptrTest ); } groupThreads.join_all(); delete pThrottle; return 0; } </pre> en-us Boost C++ Libraries /htdocs/site/boost.png https://svn.boost.org/trac10/ticket/706 Trac 1.4.3 Anthony Williams Fri, 11 Aug 2006 13:57:43 GMT <link>https://svn.boost.org/trac10/ticket/706#comment:1 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/706#comment:1</guid> <description> <pre class="wiki">Logged In: YES user_id=60756 This is not a bug, but a property of conditions. If you are waiting on a predicate, use the predicate version of wait: cond.wait(some_lock,some_predicate) Alternatively, test isAllowed() yourself in a loop, and keep waiting on the condition until isAllowed is true. The docs for pthread_cond_wait say: "When using condition variables there is always a Boolean predicate involving shared variables associated with each condition wait that is true if the thread should proceed. Spurious wakeups from the pthread_cond_timedwait() or pthread_cond_wait() functions may occur. Since the return from pthread_cond_timedwait() or pthread_cond_wait() does not imply anything about the value of this predicate, the predicate should be re-evaluated upon such return." and the same applies to boost::condition::wait. </pre> </description> <category>Ticket</category> </item> <item> <dc:creator>davevest</dc:creator> <pubDate>Fri, 11 Aug 2006 14:05:07 GMT</pubDate> <title>status changed https://svn.boost.org/trac10/ticket/706#comment:2 https://svn.boost.org/trac10/ticket/706#comment:2 <ul> <li><strong>status</strong> <span class="trac-field-old">assigned</span> → <span class="trac-field-new">closed</span> </li> </ul> Ticket