fork download
  1. #include <thread>
  2. #include <iostream>
  3. #include <sstream>
  4. #include <future>
  5. #include <queue>
  6. #include <condition_variable>
  7. #include <mutex>
  8.  
  9. // Convenience type definition
  10. using job = std::packaged_task<void()>;
  11.  
  12. // Some data associated to each thread.
  13. struct thread_data
  14. {
  15. int id; // Could use thread::id, but this is filled before the thread is started
  16. std::thread t; // The thread object
  17. std::queue<job> jobs; // The job queue
  18. std::condition_variable cv; // The condition variable to wait for threads
  19. std::mutex m; // Mutex used for avoiding data races
  20. bool stop = false; // When set, this flag tells the thread that it should exit
  21. };
  22.  
  23. // The thread function executed by each thread
  24. void thread_func(thread_data* pData)
  25. {
  26. std::unique_lock<std::mutex> l(pData->m, std::defer_lock);
  27. while (true)
  28. {
  29. l.lock();
  30.  
  31. // Wait until the queue won't be empty or stop is signaled
  32. pData->cv.wait(l, [pData] () {
  33. return (pData->stop || !pData->jobs.empty());
  34. });
  35.  
  36. // Stop was signaled, let's exit the thread
  37. if (pData->stop) { return; }
  38.  
  39. // Pop one task from the queue...
  40. job j = std::move(pData->jobs.front());
  41. pData->jobs.pop();
  42.  
  43. l.unlock();
  44.  
  45. // Execute the task!
  46. j();
  47. }
  48. }
  49.  
  50. // Function that creates a simple task
  51. job create_task(int id, int jobNumber)
  52. {
  53. job j([id, jobNumber] ()
  54. {
  55. std::stringstream s;
  56. s << "Hello " << id << "." << jobNumber << std::endl;
  57. std::cout << s.str();
  58. });
  59.  
  60. return j;
  61. }
  62.  
  63. int main()
  64. {
  65. const int numThreads = 4;
  66. const int numJobsPerThread = 10;
  67. std::vector<std::future<void>> futures;
  68.  
  69. // Create all the threads (will be waiting for jobs)
  70. thread_data threads[numThreads];
  71. int tdi = 0;
  72. for (auto& td : threads)
  73. {
  74. td.id = tdi++;
  75. td.t = std::thread(thread_func, &td);
  76. }
  77.  
  78. //=================================================
  79. // Start assigning jobs to each thread...
  80.  
  81. for (auto& td : threads)
  82. {
  83. for (int i = 0; i < numJobsPerThread; i++)
  84. {
  85. job j = create_task(td.id, i);
  86. futures.push_back(j.get_future());
  87.  
  88. std::unique_lock<std::mutex> l(td.m);
  89. td.jobs.push(std::move(j));
  90. }
  91.  
  92. // Notify the thread that there is work do to...
  93. td.cv.notify_one();
  94. }
  95.  
  96. // Wait for all the tasks to be completed...
  97. for (auto& f : futures) { f.wait(); }
  98. futures.clear();
  99.  
  100.  
  101. //=================================================
  102. // Here the main thread does something...
  103.  
  104. std::cin.get();
  105.  
  106. // ...done!
  107. //=================================================
  108.  
  109.  
  110. //=================================================
  111. // Posts some new tasks...
  112.  
  113. for (auto& td : threads)
  114. {
  115. for (int i = 0; i < numJobsPerThread; i++)
  116. {
  117. job j = create_task(td.id, i);
  118. futures.push_back(j.get_future());
  119.  
  120. std::unique_lock<std::mutex> l(td.m);
  121. td.jobs.push(std::move(j));
  122. }
  123.  
  124. // Notify the thread that there is work do to...
  125. td.cv.notify_one();
  126. }
  127.  
  128. // Wait for all the tasks to be completed...
  129. for (auto& f : futures) { f.wait(); }
  130. futures.clear();
  131.  
  132. // Send stop signal to all threads and join them...
  133. for (auto& td : threads)
  134. {
  135. std::unique_lock<std::mutex> l(td.m);
  136. td.stop = true;
  137. td.cv.notify_one();
  138. }
  139.  
  140. // Join all the threads
  141. for (auto& td : threads) { td.t.join(); }
  142. }
Success #stdin #stdout 0.01s 5284KB
stdin
Standard input is empty
stdout
Hello 3.0
Hello 3.1
Hello 3.2
Hello 3.3
Hello 3.4
Hello 3.5
Hello 3.6
Hello 3.7
Hello 3.8
Hello 3.9
Hello 2.0
Hello 2.1
Hello 2.2
Hello 2.3
Hello 2.4
Hello 2.5
Hello 2.6
Hello 2.7
Hello 2.8
Hello 2.9
Hello 1.0
Hello 1.1
Hello 1.2
Hello 1.3
Hello 1.4
Hello 1.5
Hello 1.6
Hello 1.7
Hello 1.8
Hello 1.9
Hello 0.0
Hello 0.1
Hello 0.2
Hello 0.3
Hello 0.4
Hello 0.5
Hello 0.6
Hello 0.7
Hello 0.8
Hello 0.9
Hello 1.0
Hello 1.1
Hello 1.2
Hello 1.3
Hello 1.4
Hello 1.5
Hello 1.6
Hello 1.7
Hello 1.8
Hello 1.9
Hello 2.0
Hello 2.1
Hello 2.2
Hello 2.3
Hello 2.4
Hello 2.5
Hello 2.6
Hello 2.7
Hello 2.8
Hello 2.9
Hello 3.0
Hello 3.1
Hello 3.2
Hello 3.3
Hello 3.4
Hello 3.5
Hello 3.6
Hello 3.7
Hello 3.8
Hello 3.9
Hello 0.0
Hello 0.1
Hello 0.2
Hello 0.3
Hello 0.4
Hello 0.5
Hello 0.6
Hello 0.7
Hello 0.8
Hello 0.9