Boost logo

Boost Users :

Subject: Re: [Boost-users] Condition Variable Notify
From: Matt Fair (matt.fair_at_[hidden])
Date: 2012-03-25 01:25:01


Just to finalize this thread for those who are interested, the use of
the condition variables that was discussed before with Johns's
suggestion worked great. The other issues that I brought up were a
result of my own code that caused some memory issues that I resolved.
Thanks!
Matt

On Fri, Mar 23, 2012 at 3:22 PM, Matt Fair <matt.fair_at_[hidden]> wrote:
> 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