2012-03-28 35 views
0

我想用boost::timed_wait來等待事件或在5秒後超時。我的問題是我的timed_wait只接受第一次通知。從boost :: 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

不是答案,因爲我不確定代碼中發生了什麼,但條件變量不僅僅是信號,它們應該用來表示共享條件中的變化。看到這個例子:http://www.justsoftwaresolutions.co.uk/thread/implementing-a-thread-safe-queue-using-condition-variables.html – stefaanv 2012-03-28 11:12:49

+0

在你的代碼中,條件可能是一個忙標誌,所以stateMachine可能有「busy = true; while(busy &&!rc){rc = m_Condition.timed_wait(...);}」 – stefaanv 2012-03-28 11:16:09

+0

@stefaanv感謝您的建議。我讀過你發佈的那篇文章,好吧,也許我使用'timed_wait'不是爲了通常的預期目的,但它仍然應該做這筆交易。其實他們在那裏使用的實現和我的一樣。 給你的第二個評論:忙旗應該做什麼?我的意思是我的問題是我的'timed_wait'只在第一次調用後返回一個超時值和一個返回值'false'。我可以調用'notify_all()'所有我想要的..不會改變任何東西:/ – Toby 2012-03-28 11:22:42

回答

0

好吧,對我來說不是最聰明的時刻,我真的解決了這個問題。以上發佈的代碼正在編譯並按預期工作。事件或超時處理中存在實際問題。由於發生的事情與timed_wait絕對無關,我想我不需要在這裏解釋它。所以這個問題可以結束。

UPDATE:

當然,上面的代碼不會因爲缺少一個調度方法的工作。爲了這個目的,我會在這裏提到它:爲了測試的目的,我在我的主函數中創建了一個對象myClass_A,啓動狀態機,然後從我的主函數調用callbackEvent。這實際上有效!

+0

好了,上面貼的代碼不能按預期工作,因爲沒有派遣和回叫,但是你的問題解決了,所以這是最重要的。 – stefaanv 2012-03-28 15:13:24

+0

好吧做了一點更新 – Toby 2012-03-29 09:23:38

0

不,你不必重置條件變量,是的它可以多次工作。

我相信你所看到的是一個僵局,而不是在m_condition第二次等待時失敗。當您在stateMachine()中調用timed_wait()時,您的互斥鎖將被解鎖,並且在timed_wait()返回時它將被重新鎖定。我在猜測,在等待的遺漏代碼中,您正在調用callbackEvent()。該方法試圖鎖定互斥鎖,但它不能,因爲(a)它已經鎖定在調用者(stateMachine())和(b)boost :: mutex不可重入。您可以嘗試使用例如改爲recursive_mutex。

+0

我也這麼認爲,但代碼(我省略 - >超時或事件)不是很多。所以如果我玩這個,它會這樣: 1.'timed_wait'返回(第一次) 2.「事件」代碼被執行。 3.接下來司令部派出 4.'timed_wait'解鎖互斥量 5.回調可以執行 再說 - 我與調試檢查 - 我的代碼實際上執行了'notify_all'多次 – Toby 2012-03-28 11:07:17