2014-10-18 49 views
4

我想創建一個事件循環類,它將在它自己的線程上運行,支持將任務作爲std::functions添加並執行它們。 對於這一點,我使用的是SafeQueue從這裏:https://stackoverflow.com/a/16075550/1069662C++ 11事件循環與線程安全隊列

class EventLoop 
{ 
public: 
typedef std::function<void()> Task; 

EventLoop(){ stop=false; } 

void add_task(Task t) { queue.enqueue(t); } 

void start(); 

void stop() { stop = true; } 

private: 
    SafeQueue<Task> queue; 
    bool stop; 
}; 

void EventLoop::start() 
{ 
    while (!stop) { 
     Task t = queue.dequeue(); // Blocking call 
     if (!stop) { 
      t(); 
     } 
    }  

    cout << "Exit Loop"; 
} 

然後,你會使用這樣的:

EventLoop loop; 
std::thread t(&EventLoop::start, &loop); 

loop.add_task(myTask); 
// do smth else 

loop.stop(); 
t.join(); 

我的問題是:如何阻止正常的線程? 由於阻塞隊列調用,此處stop不能退出循環。

+0

作爲一個說明,我認爲這也可能有一個'idle/repeat'列表。 – 2014-10-18 17:45:41

+0

是否有'bool SafeQueue :: try_dequeue(Task&out,std :: chrono :: milliseconds timeout);''或類似的? – 2014-10-18 17:48:14

+0

如果可能的話,我還會考慮TBB的[併發隊列](http://www.threadingbuildingblocks.org/docs/help/tbb_userguide/Concurrent_Queue_Classes.htm)容器的高性能,而不是依賴簡單的阻塞互斥體。 – sjdowling 2014-10-18 19:54:14

回答

4

排隊等待「毒丸」停止任務。這會解除隊列等待的阻塞並直接請求線程清理並退出,或者允許消費者線程檢查'stop'布爾值。

這是假設您需要在應用程序終止之前停止線程/任務。如果我能擺脫它,我通常不會這麼做。

+0

謝謝..明顯 – yandreiy 2014-10-18 19:41:46

1

另一種方法:只是排隊引發異常的任務。對您的代碼進行少許修改:

class EventLoop { 

// ... 

    class stopexception {}; 

// ... 


    void stop() 
    { 
      add_task(
       // Boring function that throws a stopexception 
     ); 
    } 
}; 

void EventLoop::start() 
{ 
    try { 
     while (1) 
     { 
      Task t = queue.dequeue(); // Blocking call 
      t(); 
     } 
    } catch (const stopexception &e) 
    { 
     cout << "Exit Loop"; 
    } 
} 

不使用例外,對於那些誰是對它們過敏的替代,將重新定義的任務,因爲這需要一個事件循環引用作爲其唯一參數的函數, stop()排隊一個任務,該任務設置突破主循環的標誌。