
Hello, I am using boost condition_variables to block while waiting for an asynchronous response. I am seeing an error that happens at random whenever I am releasing the lock just before calling notify_one. The error goes away if I keep the lock and release after notify_one. Here is the code: class BlockingRequest{ public: // predicate class class ResponseStatus { public: ResponseStatus( bool& received ) : m_received( received ) { } bool operator()() const { return m_received; } private: bool& m_received; }; //blocking request std::string Request( const std::string& request ) { boost::mutex::scoped_lock lock( mutex ); //perform asynchronous request through network or something else, pass RequestHandler as a handler boost::posix_time::milliseconds timeoutDuration( 10000 ); //wait for 10 seconds if( !condition.timed_wait( lock, timeoutDuration, ResponseStatus( received ) ) ) { throw std::exception( "Request timed out" ); } return receivedMessage; } //some other thread calls this function void RequestHandler( const std::string& message, void* caller ) { BlockingRequest* myRequest = reinterpret_cast< BlockingRequest* >( caller ); boost::mutex::scoped_lock lock( myRequest->mutex ); myRequest->receivedMessage = message; myRequest->received = true; /* if this next line in bold is commented out, code works fine... contrary to Boost documentation. http://www.boost.org/doc/libs/1_41_0/doc/html/thread/synchronization.html#th... */ *lock.unlock();* myRequest->condition.notify_one(); } };

AMDG Alessandro Bellina wrote:
I am using boost condition_variables to block while waiting for an asynchronous response. I am seeing an error that happens at random whenever I am releasing the lock just before calling notify_one. The error goes away if I keep the lock and release after notify_one.
What error do you get? In Christ, Steven Watanabe

I get an assertion failed error... but I don't know if that would help:
"_Pvector == NULL || (((_Myvec *)_Pvector)->_Myfirst <= _Ptr && _Ptr <=
((_Myvec *)_Pvector->_Mylast)" and soon after everything blows up.
Here's a thought.. suppose that the thread receiving the response (so the
one that calls notify_one), locks the mutex multiple times (without
notifying every time)...
like this:
boost::mutex::scoped_lock lock( mutex );
if( response == "something I care about" )
{
lock.unlock();
condition.notify_one();
}
and multiple responses did come through. What would the effects be in the
condition variable?
Why is it that since we already hold a mutex in the requesting thread, the
thread handling the response can successfully lock that mutex too? Does the
condition.wait call set something in the lock?
Thanks,
Alessandro
On Wed, Dec 9, 2009 at 9:28 AM, Steven Watanabe
AMDG
Alessandro Bellina wrote:
I am using boost condition_variables to block while waiting for an asynchronous response. I am seeing an error that happens at random whenever I am releasing the lock just before calling notify_one. The error goes away if I keep the lock and release after notify_one.
What error do you get?
In Christ, Steven Watanabe
_______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users

Why is it that since we already hold a mutex in the requesting thread, the thread handling the response can successfully lock that mutex too? Does the condition.wait call set something in the lock?
Thanks,
Alessandro The idea of wait on a condition variable is to atomically release the mutex and enter some sort of sleep mode, which is later interrupted by a wake-up from a different thread. At that point the mutex is re-aquired. So, yes, condition.wait() unlocks the mutex and waits for notification, then locks the mutex again. -- Nikolai

Thanks Nikolai, That explains why the second thread can lock that mutex. From what you are saying then, the sleeping thread will wake up and reacquire the lock after notify is called. So the thread that calls notify should not hold that lock when this happens or you could have deadlock right?. Alessandro On Thu, Dec 10, 2009 at 12:25 PM, Nikolai N Fetissov < nikolai-boost@fetissov.org> wrote:
Why is it that since we already hold a mutex in the requesting thread,
the
thread handling the response can successfully lock that mutex too? Does the condition.wait call set something in the lock?
Thanks,
Alessandro
The idea of wait on a condition variable is to atomically release the mutex and enter some sort of sleep mode, which is later interrupted by a wake-up from a different thread. At that point the mutex is re-aquired. So, yes, condition.wait() unlocks the mutex and waits for notification, then locks the mutex again.
-- Nikolai
_______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users

Thanks Nikolai, That explains why the second thread can lock that mutex. From what you are saying then, the sleeping thread will wake up and reacquire the lock after notify is called. So the thread that calls notify should not hold that lock when this happens or you could have deadlock right?.
Alessandro, The thread calling the 'notify' can, but does not have to, hold a mutex at the time. In theory all the notify() function does is mark the thread sleeping on the condition as runnable. There's no deadlock here. Also google for 'spurious wakeup' to get a firm hold on mutex/cv concepts. Cheers, -- Nikolai

This is scheme which I often use: // Common for both threads boost::mutex mutex; boost::condition condition; // Thread1: boost::xtime waitingTime(set value of waiting time) { boost::mutex::scoped_lock lock(mutex) do { if (some_event occurred) { do something after received event return; // exit point after receive event } } while (condition.timed_wait(lock, waitingTime)); do something after timeout occurred // exit point after timeout } //Thread2 { boost::mutex::scoped_lock lock(mutex); set some event which is been waiting thread1 condition.notify_one(); } Maybe will be useful for you. Adam Nikolai N Fetissov wrote:
Thanks Nikolai, That explains why the second thread can lock that mutex. From what you are saying then, the sleeping thread will wake up and reacquire the lock after notify is called. So the thread that calls notify should not hold that lock when this happens or you could have deadlock right?.
Alessandro,
The thread calling the 'notify' can, but does not have to, hold a mutex at the time. In theory all the notify() function does is mark the thread sleeping on the condition as runnable. There's no deadlock here. Also google for 'spurious wakeup' to get a firm hold on mutex/cv concepts.
Cheers, -- Nikolai
_______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users

Spurious wake ups?
Thanks for posting your example. I don't really know why we need to set
"some_event_occurred". Is this the recommended usage?
Other than your first iteration (where you need the flag, but that is
because you are using a do/while as opposed to a while loop), are we
supposed to get spurious wake ups (i.e. will timed_wait return true even if
we didn't call notify_one)?
Alessandro
On Thu, Dec 10, 2009 at 4:11 PM, Adam Szeliga
This is scheme which I often use:
// Common for both threads boost::mutex mutex; boost::condition condition;
// Thread1:
boost::xtime waitingTime(set value of waiting time) {
boost::mutex::scoped_lock lock(mutex) do { if (some_event occurred) { do something after received event return; // exit point after receive event } } while (condition.timed_wait(lock, waitingTime)); do something after timeout occurred // exit point after timeout }
//Thread2
{ boost::mutex::scoped_lock lock(mutex); set some event which is been waiting thread1 condition.notify_one(); }
Maybe will be useful for you. Adam
Nikolai N Fetissov wrote:
Thanks Nikolai, That explains why the second thread can lock that mutex. From what you are saying then, the sleeping thread will wake up and reacquire the lock after notify is called. So the thread that calls notify should not hold that lock when this happens or you could have deadlock right?.
Alessandro,
The thread calling the 'notify' can, but does not have to, hold a mutex at the time. In theory all the notify() function does is mark the thread sleeping on the condition as runnable. There's no deadlock here. Also google for 'spurious wakeup' to get a firm hold on mutex/cv concepts.
Cheers, -- Nikolai
_______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users
_______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users

- Yes you are right, loop is needed due to spurious wake ups. - timed_wait return true if condition is notified or due to spurious wake ups. We need additional variable for distinguish that. - The flag some_event_occurred is needed in case where conditional.notify_one is called just before calling conditional.timed_wait. Example without flag some_event_occurred: thread 2 -> lock mutex thread 1 -> hold on mutex thread 2 -> condition.notify_one() thread 2 -> unlock mutex thread 1 -> lock mutex thread 1-> hold on condition.timed_wait and waiting up to timeout occurred In this example notify_one "is missing" by thread1 If is it still unclear, please ask more. Regards Adam Alessandro Bellina wrote:
Spurious wake ups?
Thanks for posting your example. I don't really know why we need to set "some_event_occurred". Is this the recommended usage? Other than your first iteration (where you need the flag, but that is because you are using a do/while as opposed to a while loop), are we supposed to get spurious wake ups (i.e. will timed_wait return true even if we didn't call notify_one)?
Alessandro
On Thu, Dec 10, 2009 at 4:11 PM, Adam Szeliga
mailto:aszeliga.xsoftware@gmail.com> wrote: This is scheme which I often use:
// Common for both threads boost::mutex mutex; boost::condition condition;
// Thread1:
boost::xtime waitingTime(set value of waiting time) {
boost::mutex::scoped_lock lock(mutex) do { if (some_event occurred) { do something after received event return; // exit point after receive event } } while (condition.timed_wait(lock, waitingTime)); do something after timeout occurred // exit point after timeout }
//Thread2
{ boost::mutex::scoped_lock lock(mutex); set some event which is been waiting thread1 condition.notify_one(); }
Maybe will be useful for you. Adam
Nikolai N Fetissov wrote: >> Thanks Nikolai, >> That explains why the second thread can lock that mutex. From what you are >> saying then, the sleeping thread will wake up and reacquire the lock after >> notify is called. So the thread that calls notify should not hold that >> lock >> when this happens or you could have deadlock right?. >> >> > > Alessandro, > > The thread calling the 'notify' can, but does not have to, hold > a mutex at the time. In theory all the notify() function does is > mark the thread sleeping on the condition as runnable. There's > no deadlock here. Also google for 'spurious wakeup' to get a firm > hold on mutex/cv concepts. > > Cheers, > -- > Nikolai > > _______________________________________________ > Boost-users mailing list > Boost-users@lists.boost.org mailto:Boost-users@lists.boost.org > http://lists.boost.org/mailman/listinfo.cgi/boost-users >
_______________________________________________ Boost-users mailing list Boost-users@lists.boost.org mailto:Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users
------------------------------------------------------------------------
_______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users
participants (4)
-
Adam Szeliga
-
Alessandro Bellina
-
Nikolai N Fetissov
-
Steven Watanabe