2017-08-09 13 views
0

在我的項目中,函數clipsUpdate可以讀取CLIPS設置的一些事實,而不受我的C++代碼的干擾。根據讀取的事實,clipsUpdate調用所需的函數。定期檢查一個條件而不會阻止

void updateClips(void) 
{ 
    // read clipsAction 

    switch(clipsAction) 
    { 
     case ActMove: 
       goToPosition (0, 0, clipsActionArg); 
       break; 
    } 
} 

goToPosition功能,消息被髮送到車輛移動到指定位置,然後一個while循環用於等待直到車輛到達的位置。

void goToPosition(float north, float east, float down) 
{ 
    // Prepare and send the message 

    do 
    { 
      // Read new location information. 
    }while(/*Specified position reached?*/) 
} 

的問題是,應該updateClips每500毫秒被調用,當goToPosition函數被調用,執行被阻止,直到達到目標位置。在此等待期間,可能會發生需要停車的情況。因此,updateClip無論如何應該每隔500毫秒調用一次,如果它正在運行,它應該能夠停止執行goToPosition

我嘗試使用線程如下,但它沒有成功與我一起工作,我很難調試。我認爲可以用更簡單更清潔的方式來完成。

case ActMove: 
     std::thread t1(goToPosition, 0, 0, clipsActionArg); 
     t1.detach(); 
     break; 

我的問題是,我怎麼能檢查是否達到不阻塞執行,即目標位置,而無需使用while

+1

您需要正確實現多線程應用程序或使其成爲事件驅動。兩者都不簡單。 – Slava

+0

感謝Slava您的快速回答。我認爲可能有其他更簡單的方法。我會盡力去解決其中的一個問題。你建議哪一個?爲什麼? –

回答

1

你可能想要一個事件驅動的模型。

在事件驅動模型中,您的主引擎是一個緊密的循環,它讀取事件,更新狀態,然後等待更多事件。

有些事件是基於時間的,其他事件是基於輸入的。

被允許阻塞主線程的唯一代碼是主循環,在主循環中它阻塞,直到定時器命中或新事件到達。

它可能非常粗略看起來像這樣:

using namespace std::literals::chrono_literals; 
void main_loop(engine_state* state) { 
    bool bContinue = true; 
    while(bContinue) { 
    update_ui(state); 
    while(bContinue && process_message(state, 10ms)) { 
     bContinue = update_state(state); 
    } 
    bContinue = update_state(state); 
    } 
} 

update_ui提供反饋給用戶,如果需要的話。

process_message(state, duration)尋找要處理的消息,或尋找10ms。如果它看到一條消息(如goToPosition),它會修改狀態以反映該消息(例如,它可能會存儲所需的描述)。它不阻擋,也不需要很多時間。

如果在duration時間內沒有收到任何消息,它將以任何方式返回而不會修改state(我假設即使沒有新的輸入/消息發生,也希望事情發生)。

update_state需要state並發展它。 state可能有最後更新的時間戳;然後update_state會使「物理學」反映自上一次以來的時間。或者做任何其他更新。

關鍵是process_message不做狀態(它編碼慾望),而update_state提前「現實」。如果主循環應該退出,則返回false

update_state每調用process_message調用一次。

updateClips被每500ms調用一次可以編碼爲消息隊列中的重複自動事件process_message讀取。

void process_message(engine_state* state, std::chrono::milliseconds ms) { 
    auto start = std::chrono::high_resolution_clock::now(); 
    while (start + ms > std::chrono::high_resolution_clock::now()) { 
    // engine_state::delayed is a priority_queue of timestamp/action 
    // ordered by timestamp: 
    while (!state->delayed.empty()) { 
     auto stamp = state->delayed.front().stamp; 
     if (stamp >= std::chrono::high_resolution_clock::now()) { 
     auto f = state->queue.front().action; 
     state->queue.pop(); 
     f(stamp, state); 
     } else { 
     break; 
     } 
    } 
    //engine_state.queue is std::queue<std::function<void(engine_state*)>> 
    if (!state->queue.empty()) { 
     auto f = state->queue.front(); 
     state->queue.pop(); 
     f(state); 
    } 
    } 
} 

重複的輪詢被實現爲延遲作用的是,作爲其第一個操作中,該一個之後插入一個新的延遲作用,由於500毫秒。我們在行動開始的時候通過。

可以將「正常」事件推入正常操作queue,這是std::function<void(engine_state*)>的一個序列並按順序執行。

如果無事可做,上述函數忙碌等待ms時間,然後返回。在某些情況下,我們可能想要去睡覺。

這只是事件循環的草圖。互聯網上有很多很多。

+0

很多人都非常感謝您的回答,並感謝您一直致力於寫作。我會慢慢瀏覽,並會爲事件驅動模型尋找一個很好的教程。謝謝 –

相關問題