boost::timed_wait中的Notify条件变量只工作一次



我想使用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。这确实有效!

最新更新