fork(7) download
  1. #include <iostream>
  2. #include <thread>
  3. #include <iostream>
  4. #include <condition_variable>
  5. #include <list>
  6.  
  7. using namespace std;
  8.  
  9. class Worker
  10. {
  11. public:
  12. Worker(bool run) : m_Running(run) { if (run) private_start(); }
  13. Worker() : m_Running(false) { }
  14. ~Worker() { stop(); }
  15.  
  16. template<typename... Args>
  17. void push_task(Args&&... args)
  18. {
  19. {
  20. std::lock_guard<std::mutex> lk(m_Mutex);
  21. m_Queue.push_back(std::bind(std::forward<Args>(args)...));
  22. }
  23.  
  24. m_Condition.notify_all();
  25. }
  26.  
  27. void start()
  28. {
  29. {
  30. std::lock_guard<std::mutex> lk(m_Mutex);
  31. if (m_Running == true) return;
  32. m_Running = true;
  33. }
  34.  
  35. private_start();
  36. }
  37.  
  38. void stop()
  39. {
  40. {
  41. std::lock_guard<std::mutex> lk(m_Mutex);
  42. if (m_Running == false) return;
  43. m_Running = false;
  44. }
  45.  
  46. m_Condition.notify_all();
  47. m_Thread.join();
  48. }
  49.  
  50. private:
  51. void private_start()
  52. {
  53. m_Thread = std::thread([this]
  54. {
  55. for (;;)
  56. {
  57. decltype(m_Queue) local_queue;
  58. {
  59. std::unique_lock<std::mutex> lk(m_Mutex);
  60. m_Condition.wait(lk, [&] { return !m_Queue.empty() + !m_Running; });
  61.  
  62. if (!m_Running)
  63. {
  64. for (auto& func : m_Queue)
  65. func();
  66.  
  67. m_Queue.clear();
  68. return;
  69. }
  70.  
  71. std::swap(m_Queue, local_queue);
  72. }
  73.  
  74. for (auto& func : local_queue)
  75. func();
  76. }
  77. });
  78. }
  79.  
  80. private:
  81. std::condition_variable m_Condition;
  82. std::list<std::function<void()>> m_Queue;
  83. std::mutex m_Mutex;
  84. std::thread m_Thread;
  85. bool m_Running = false;
  86. };
  87.  
  88. void do_work(unsigned id)
  89. {
  90. // uncomment if you want to sync the output stream
  91. // static std::mutex cout_mutex;
  92. // std::lock_guard<std::mutex> lk(cout_mutex);
  93. std::cout << id << std::endl;
  94. }
  95.  
  96. int main()
  97. {
  98. {
  99. Worker workers[3];
  100. int counter = 0;
  101.  
  102. for (auto& worker : workers)
  103. worker.start();
  104.  
  105. for (auto& worker : workers)
  106. {
  107. for (int i = 0; i < 5; i++)
  108. worker.push_task(do_work, ++counter + i);
  109. }
  110. }
  111.  
  112. std::cout << "finish" << std::endl;
  113. getchar();
  114.  
  115. return 0;
  116. }
Success #stdin #stdout 0s 28048KB
stdin
Standard input is empty
stdout
11
13
15
17
19
6
8
10
12
14
1
3
5
7
9
finish