fork(1) download
  1. #include <algorithm>
  2. #include <atomic>
  3. #include <chrono>
  4. #include <functional>
  5. #include <iostream>
  6. #include <iterator>
  7. #include <string>
  8. #include <thread>
  9. #include <vector>
  10.  
  11. template <typename TaskType>
  12. struct task_list {
  13.  
  14. struct node {
  15. node(std::function<TaskType> task)
  16. : task(task), next(nullptr) { }
  17.  
  18. std::function<void()> task;
  19. std::atomic<node*> next;
  20. };
  21.  
  22. std::atomic<node*> tail{ nullptr };
  23.  
  24. void push_task(std::function<TaskType> task) {
  25. node* new_node = new node(task);
  26. node* old_tail = tail.exchange(new_node, std::memory_order_relaxed);
  27.  
  28. if(old_tail == nullptr || old_tail->next.exchange(new_node, std::memory_order_consume) == old_tail) {
  29. delete old_tail;
  30.  
  31. node* current = new_node;
  32. for(;;) {
  33. current->task();
  34. node* expected = current->next.exchange(current, std::memory_order_release);
  35. if(expected == nullptr) return;
  36. else {
  37. delete current;
  38. current = expected;
  39. }
  40. }
  41. }
  42. }
  43.  
  44. ~task_list() {
  45. delete tail.load();
  46. }
  47. };
  48.  
  49. int main() {
  50. task_list<void()> list;
  51.  
  52. std::vector<std::thread> threads;
  53. std::string hello = "Hello, World!\n";
  54.  
  55. auto task = [&list, &hello] {
  56. std::transform(std::begin(hello), std::end(hello), std::ostream_iterator<char>(std::cout), [](auto c) {
  57. std::this_thread::yield();
  58. std::this_thread::yield();
  59. return c;
  60. });
  61. };
  62.  
  63. std::cout << "Ugly:\n";
  64. for(int i = 0; i < 10; ++i) {
  65. threads.emplace_back([&list, task] {
  66. task();
  67. });
  68. }
  69.  
  70. for(auto& thread : threads)
  71. if(thread.joinable()) thread.join();
  72. threads.clear();
  73.  
  74. std::cout << "\nNice:\n";
  75. for(int i = 0; i < 10; ++i) {
  76. threads.emplace_back([&list, task] {
  77. list.push_task(task);
  78. });
  79. }
  80.  
  81. for(auto& thread : threads)
  82. if(thread.joinable()) thread.join();
  83. }
  84.  
Success #stdin #stdout 0s 46480KB
stdin
Standard input is empty
stdout
Ugly:
HHeelllloo,, W HorWeldol!rl
lod,! W
Hoerllldo!,
 HWeolrllod,! 
WHoerllldo!,
 HWeolrllod,! 
WHoerllldo!,
 HWeolrllod,! 
WHoerllldo!,
 World!

Nice:
Hello, World!
Hello, World!
Hello, World!
Hello, World!
Hello, World!
Hello, World!
Hello, World!
Hello, World!
Hello, World!
Hello, World!