Boost logo

Boost Users :

Subject: Re: [Boost-users] Condition Variable Notify
From: Matt Fair (matt.fair_at_[hidden])
Date: 2012-03-23 17:22:56


John,
Thanks for your suggestion for moving m_receiveAck to the bottom of
waitForAck, makes much more sense. The simple code example works as
expected, and thanks for your input that it doesn't matter the order
of the ack and wait.

I'm still however having some issues in my full code, which has send
and receive on two separate threads. When using timed_wait after a
couple wait/ack successful iterations, m_receivedAck is set to true in
receiveAck(), but back in waitForAck() after the wait times out
m_receivedAck is still false. What could possibly cause this?
Changing this variable to volatile does not have any effect either.
On top of this, the waitForAck() times out even though when I do a
m_ackCond.notify_one() in receiveAck(), it seems to have no effect.
Has anyone ever seen this?

My current problem may be an issue that I'll just have to continue
slog through myself to fine my application specific bug, but if anyone
has seen anything like this your insight would be most helpful.

Thanks!
Matt

On Thu, Mar 22, 2012 at 2:16 PM, John Rocha <jrr_at_[hidden]> wrote:
> 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 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