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
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
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@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users
_______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users