#include<iostream>
#include<thread>
#include<vector>
#include<atomic>
#include<string>
#include<mutex>
#include<condition_variable>
std::atomic<long long> value;
std::atomic<bool> stop_signal;
class Thread {
private:
bool working_, exit_;
std::thread thread_;
std::mutex mutex_;
std::condition_variable sleep_condition_;
unsigned int id_;
public:
Thread(unsigned int id) : working_(false), exit_(false), id_(id) {
thread_ = std::thread(&Thread::idleLoop, this);
}
~Thread() {
thread_.join();
}
void work() {
while (!stop_signal) {
long long tmp = ++value;
if (tmp % 1000000 == 0) {
std::cout << tmp << "を踏んだのは" << id_ << std::endl;
}
}
working_ = false;
}
void idleLoop() {
while (!exit_) {
{
std::unique_lock<std::mutex> lock(mutex_);
sleep_condition_.wait(lock, [this]() {
return working_ || exit_;
});
}
if (exit_)
break;
work();
{
std::unique_lock<std::mutex> lock(mutex_);
working_ = false;
sleep_condition_.notify_one();
}
}
}
void startWork() {
std::unique_lock<std::mutex> lock(mutex_);
working_ = true;
sleep_condition_.notify_one();
}
void waitForFinishWork() {
std::unique_lock<std::mutex> lock(mutex_);
sleep_condition_.wait(lock, [this]() {
return !working_;
});
}
};
int main() {
unsigned int max_thread_num = std::thread::hardware_concurrency();
std::cout << "max_thread_num = " << max_thread_num << std::endl;
std::cout << "before value = " << value << std::endl;
std::vector<Thread*> threads(max_thread_num);
for (unsigned int i = 0; i < max_thread_num; i++) {
threads[i] = new Thread(i);
}
//USIのコマンド処理部っぽいもの
std::string command;
while (std::cin >> command) {
if (command == "go") {
std::cout << "start go" << std::endl;
stop_signal = false;
for (auto& t : threads) {
t->startWork();
}
std::this_thread::sleep_for(std::chrono::milliseconds(300));
} else if (command == "stop") {
stop_signal = true;
for (auto& t : threads) {
//終了の待ち方はこんなんでいいのかな
t->waitForFinishWork();
}
break;
} else {
std::cout << "invalid input" << std::endl;
}
}
std::cout << "after value = " << value << std::endl;
}