|
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