|
Boost Users : |
Subject: Re: [Boost-users] Condition Variable Notify
From: John Rocha (jrr_at_[hidden])
Date: 2012-03-22 16:16:49
Hello Matt,
One thing that has me concerned is that waitForAck() changes m_receivedAck to
false on entrance.
so if receiveAck() is invoked first, it would grab the lock, set m_receiveAck to
true and then unlock.
Next, waitForAck() would execute, grab the lock, clear m_receiveAck, and then go
into a wait loop.
I would consider changing the logic so that m_receivedAck is initialized to
false in the class constructor, and then changed to false after the condvar, and
subordinate checks, have acted upon it (under the lock).
-=John
class Foo
{
public:
Foo () : m_receiveAck(false); // <-----------------------
void waitForAck();
void receiveAck();
private:
boost::mutex m_ackMutex;
boost::condition_variable m_ackCond;
bool m_receivedAck;
};
void Foo::waitForAck()
{
boost::mutex::scoped_lock lock(m_ackMutex);
//wait 8 seconds for ack
boost::system_time const
waitingTime=boost::get_system_time()+boost::posix_time::seconds(8);
do
{
if(m_receivedAck)
{
//got ack, break out of loop
break;
}
//Waiting for ack...
} while (m_ackCond.timed_wait(lock, waitingTime));
if(!m_receivedAck)
{
//wait for ack timed out
}
m_receivedAck=false; // <-----------------------
}
void Foo::receiveAck()
{
boost::mutex::scoped_lock lock(m_ackMutex);
m_receivedAck = true;
lock.unlock();
m_ackCond.notify_one();
}
On 3/22/2012 11:51 AM, Matt Fair wrote:
> Hello, I'm using a condition variable to notify when I get an ack
> message back. For the most part it is working like it is suppose to,
> but I have a situation where it doesn't work. Luckly the problem is
> repeatable and seems to be specific to my condition variable being
> notified, I've included a simplified version of the code, are there
> any outstanding issues? I have two threads, waitForAck() is called in
> one and receiveAck() is called in another.
>
> class Foo
> {
> public:
> void waitForAck();
> void receiveAck();
> private:
> boost::mutex m_ackMutex;
> boost::condition_variable m_ackCond;
> bool m_receivedAck;
> };
>
> void Foo::waitForAck()
> {
> boost::mutex::scoped_lock lock(m_ackMutex);
> m_receivedAck=false;
>
> //wait 8 seconds for ack
> boost::system_time const
> waitingTime=boost::get_system_time()+boost::posix_time::seconds(8);
> do
> {
>
> if(m_receivedAck)
> {
> //got ack, break out of loop
> break;
> }
>
> //Waiting for ack...
> } while (m_ackCond.timed_wait(lock, waitingTime));
>
> if(!m_receivedAck)
> {
> //wait for ack timed out
> }
> }
>
> void Foo::receiveAck()
> {
> boost::mutex::scoped_lock lock(m_ackMutex);
> m_receivedAck = true;
> lock.unlock();
> m_ackCond.notify_one();
> }
>
> So for most of the time, this works as expected. However, at a
> particular part of my code waitForAck is called, then receiveAck is
> called in the other thread, notify is sent out but for some reason
> even though i'm waiting in the timed_wait in thread 1 it waits for 8
> seconds and then says there was a timeout.
>
> So my questions are:
> 1. Does anything look off, am I using the condition variable and
> mutex correctly?
> 2. In waitForAck, I have a scope_lock that is locked, when I enter
> into timed_wait, does this unlock the mutex and the re-locks it when
> m_ackCond.notify_one() is called?
> 3. Are there any special circumstances with condition variable
> (besides receive happens before wait) where this code shouldn't behave
> as it should?
>
> Thanks for your help, I've been banging my head against the wall here with this!
> Matt
> _______________________________________________
> Boost-users mailing list
> Boost-users_at_[hidden]
> http://lists.boost.org/mailman/listinfo.cgi/boost-users
Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net