我想使用boost::timed_wait
来等待事件或在5秒后超时。我的问题是我的timed_wait
只接受第一次通知。
更准确地说:
我有一个小小的状态机。它只不过异步发送一些命令,然后检查它是否成功。这意味着在调度命令之后,我的状态机将调用m_Condition.timed_wait(lock,timeout)
。(m_Condition
是类型为boost::condition_variable
的成员变量)。
现在,如果这个异步调用成功,它将调用一个回调函数,该函数会通知m_Condition
,这样我就知道一切正常。当命令失败时,它不会调用回调函数,所以我的timed_wait
应该超时。因此,回调函数的作用无非是调用m_Condition.notify_all()
。
问题是,这只是第一次。这意味着,在第一次调用notify_all()
之后,它将不再使用该条件变量。我查看了我的回调,它总是再次调用notify_all()
,但timed_wait
刚好超时。
也许一些示例代码可以让它更清晰一点:
myClass_A.hpp
class myClass_A
{
public:
void runStateMachine(); // Starts the state machine
void callbackEvent(); // Gets called when Async Command was successful
private:
void stateMachine(); // Contains the state machine
void dispatchAsyncCommand(); // Dispatches an Asynchronous command
boost::thread m_Thread; // Thread for the state machine
boost::condition_variable m_Condition; // Condition variable for timed_wait
boost::mutex m_Mutex; // Mutex
};
myClass_A.cpp
void myClass_A::runStateMachine()
{
m_Thread = boost::thread(boost::bind(&myClass_A,this));
}
void myClass_A::dispatchAsyncCommand()
{
/* Dispatch some command Async and then return */
/* The dispatched Command will call callbackEvent() when done */
}
void myClass_A::stateMachine()
{
boost::mutex::scoped_lock lock(m_Mutex);
while(true)
{
dispatchAsynCommand();
if(!m_Condition.timed_wait(lock, boost::posix_time::milliseconds(5000)))
{
// Timeout
}
else
{
// Event
}
}
}
void myClass_A::callbackEvent()
{
boost::mutex::scoped_lock lock(m_Mutex);
m_Condition.notify_all();
}
那么我现在该怎么办呢?是否不能多次使用condition_variable?还是我需要以某种方式重置它?欢迎提出任何建议!
不,您不必重置条件变量,是的,它可以多次工作。
我相信您在m_condition上第二次等待时看到的是死锁,而不是失败。当您在stateMachine()中调用timed_wait()时,您的互斥对象将被解锁,当timed_wai()返回时,它将被重新锁定。我猜在等待之后丢失的代码中,您正在调用callbackEvent()。该方法试图锁定互斥体,但它不能,因为(a)它已经锁定在调用方(stateMachine())中,并且(b)boost::互斥体不是可重入的。您可以尝试使用例如recursive_mutex。
好吧,这不是我真正解决问题的最佳时机。上面发布的代码正在编译并按预期工作。实际问题在于事件或超时的处理。由于那里发生的事情与timed_wait
完全无关,我想我不需要在这里解释。所以这个问题可以结束了。
更新:
当然,由于缺少调度方法,上面的代码将不起作用。为了方便起见,我将在这里提到它:出于测试目的,我只在主函数中创建一个myClass_A
的对象,启动状态机,然后从主函数中调用callbackEvent
。这确实有效!