我想使用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?或者我需要以某种方式重置它?欢迎任何建议!
答案 0 :(得分:0)
不,您不必重置条件变量,是的,它可以多次运行。
我相信你所看到的是一个死锁,而不是在第二次等待m_condition时失败。当你在stateMachine()中调用timed_wait()时,你的互斥锁将被解锁,并在timed_wait()返回时被重新锁定。我猜测在等待的丢失代码中你调用callbackEvent()。该方法试图锁定互斥锁,但它不能,因为(a)它已经锁定在调用者(stateMachine())和(b)boost :: mutex不可重入。您可以尝试使用例如而是recursive_mutex。
答案 1 :(得分:0)
好吧,对我来说不是最亮的时刻,我实际上解决了这个问题。上面发布的代码正在编译并按预期工作。实际问题在于处理事件或超时。因为那里发生的事情与timed_wait
完全无关,我想我不需要在这里解释它。所以这个问题可以关闭。
<强>更新强>
当然,由于缺少调度方法,上述代码将无效。只是为了它,我在这里提一下:为了测试目的,我只需在我的main函数中创建一个myClass_A
的Object,启动状态机,然后从我的main函数调用callbackEvent
。这实际上有效!