fork download
  1. #include<iostream>
  2. #include<thread>
  3. #include<vector>
  4. #include<atomic>
  5. #include<string>
  6. #include<mutex>
  7. #include<condition_variable>
  8.  
  9. std::atomic<long long> value;
  10. std::atomic<bool> stop_signal;
  11.  
  12. class Thread {
  13. private:
  14. bool working_, exit_;
  15. std::thread thread_;
  16. std::mutex mutex_;
  17. std::condition_variable sleep_condition_;
  18. unsigned int id_;
  19. public:
  20. Thread(unsigned int id) : working_(false), exit_(false), id_(id) {
  21. thread_ = std::thread(&Thread::idleLoop, this);
  22. }
  23. ~Thread() {
  24. thread_.join();
  25. }
  26.  
  27. void work() {
  28. while (!stop_signal) {
  29. long long tmp = ++value;
  30. if (tmp % 1000000 == 0) {
  31. std::cout << tmp << "を踏んだのは" << id_ << std::endl;
  32. }
  33. }
  34. working_ = false;
  35. }
  36.  
  37. void idleLoop() {
  38. while (!exit_) {
  39. {
  40. std::unique_lock<std::mutex> lock(mutex_);
  41. sleep_condition_.wait(lock, [this]() {
  42. return working_ || exit_;
  43. });
  44. }
  45. if (exit_)
  46. break;
  47.  
  48. work();
  49. {
  50. std::unique_lock<std::mutex> lock(mutex_);
  51. working_ = false;
  52. sleep_condition_.notify_one();
  53. }
  54. }
  55. }
  56.  
  57. void startWork() {
  58. std::unique_lock<std::mutex> lock(mutex_);
  59. working_ = true;
  60. sleep_condition_.notify_one();
  61. }
  62.  
  63. void waitForFinishWork() {
  64. std::unique_lock<std::mutex> lock(mutex_);
  65. sleep_condition_.wait(lock, [this]() {
  66. return !working_;
  67. });
  68. }
  69. };
  70.  
  71. int main() {
  72. unsigned int max_thread_num = std::thread::hardware_concurrency();
  73. std::cout << "max_thread_num = " << max_thread_num << std::endl;
  74. std::cout << "before value = " << value << std::endl;
  75.  
  76. std::vector<Thread*> threads(max_thread_num);
  77.  
  78. for (unsigned int i = 0; i < max_thread_num; i++) {
  79. threads[i] = new Thread(i);
  80. }
  81.  
  82. //USIのコマンド処理部っぽいもの
  83. std::string command;
  84. while (std::cin >> command) {
  85. if (command == "go") {
  86. std::cout << "start go" << std::endl;
  87. stop_signal = false;
  88. for (auto& t : threads) {
  89. t->startWork();
  90. }
  91. std::this_thread::sleep_for(std::chrono::milliseconds(300));
  92. } else if (command == "stop") {
  93. stop_signal = true;
  94. for (auto& t : threads) {
  95. //終了の待ち方はこんなんでいいのかな
  96. t->waitForFinishWork();
  97. }
  98. break;
  99. } else {
  100. std::cout << "invalid input" << std::endl;
  101. }
  102. }
  103.  
  104. std::cout << "after value = " << value << std::endl;
  105. }
Success #stdin #stdout 0.3s 23456KB
stdin
go
stop
stdout
max_thread_num = 4
before value = 0
start go
1000000を踏んだのは3
2000000を踏んだのは0
3000000を踏んだのは2
4000000を踏んだのは3
5000000を踏んだのは3
6000000を踏んだのは0
7000000を踏んだのは3
8000000を踏んだのは3
9000000を踏んだのは0
10000000を踏んだのは1
11000000を踏んだのは2
12000000を踏んだのは0
13000000を踏んだのは3
14000000を踏んだのは3
15000000を踏んだのは3
16000000を踏んだのは2
17000000を踏んだのは0
18000000を踏んだのは2
19000000を踏んだのは3
20000000を踏んだのは0
21000000を踏んだのは0
22000000を踏んだのは0
23000000を踏んだのは0
24000000を踏んだのは2
25000000を踏んだのは1
26000000を踏んだのは0
27000000を踏んだのは0
28000000を踏んだのは3
29000000を踏んだのは3
30000000を踏んだのは3
31000000を踏んだのは1
32000000を踏んだのは2
33000000を踏んだのは0
34000000を踏んだのは2
35000000を踏んだのは3
36000000を踏んだのは3
37000000を踏んだのは3
38000000を踏んだのは0
39000000を踏んだのは3
after value = 39621317