Boost logo

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