-
-
Save alibitek/4228185 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <iostream> | |
#include <thread> | |
#include <future> | |
#include <chrono> | |
#include <functional> | |
#include <deque> | |
struct task_queue { | |
task_queue() = default; | |
task_queue(const task_queue &) = delete; | |
task_queue &operator =(const task_queue &) = delete; | |
void operator ()() { | |
std::function<void()> f([]{}); | |
do { | |
f(); | |
std::unique_lock<std::mutex> lk(mut); | |
cond.wait(lk, [this]() { return !queue.empty(); }); | |
f = std::move(queue.front()); | |
queue.pop_front(); | |
} while (f) ; | |
std::cout << "タスクスレッド終了\n"; | |
} | |
template <typename Fn> | |
void append_task(const Fn &f) { | |
std::unique_lock<std::mutex> lk(mut); | |
queue.push_back(f); | |
cond.notify_one(); | |
} | |
template <typename Fn> | |
auto do_sync_task(const Fn &f) -> decltype(f()) { | |
typedef decltype(f()) RetT; | |
std::packaged_task<RetT()> pt(f); | |
std::future<RetT> uf(pt.get_future()); | |
{ | |
std::unique_lock<std::mutex> lk(mut); | |
queue.push_front(ref(pt)); | |
cond.notify_one(); | |
} | |
return uf.get(); | |
} | |
void kill() { | |
std::unique_lock<std::mutex> lk(mut); | |
queue.push_front({}); | |
cond.notify_one(); | |
} | |
std::mutex mut; | |
std::condition_variable cond; | |
std::deque<std::function<void()>> queue; | |
}; | |
int main() { | |
task_queue obj; | |
std::thread th(std::ref(obj)); | |
int task_number = 0; | |
std::mutex mut; | |
std::condition_variable waiter; | |
const auto numbered_task = [&mut, &waiter](int num) -> int { | |
std::cout << "Task スタート! Number:" << num << std::endl; | |
std::unique_lock<std::mutex> lk(mut); | |
if (waiter.wait_until(lk, std::chrono::system_clock::now() + std::chrono::milliseconds(2000)) == std::cv_status::no_timeout) { | |
std::cout << "Task 中断 Number:" << num << std::endl; | |
} else { | |
std::cout << "Task 終了! Number:" << num << std::endl; | |
} | |
return num * num; | |
}; | |
while(1) | |
{ | |
std::cout << "コマンドを入れて エンターキーおしてください。(q:終了 / a:非同期タスクの追加 / s:同期タスクの実行) " << std::endl; | |
std::string str; | |
getline( std::cin, str ); | |
if (str == "q") | |
{ | |
break; | |
} | |
if (str == "a") | |
{ | |
obj.append_task(std::bind(numbered_task, task_number)); | |
std::cout << "task " << task_number << " を登録しました。" << std::endl; | |
task_number++; | |
} | |
if (str == "s") | |
{ | |
std::cout << "task " << task_number << " を同期実行します。" << std::endl; | |
const auto r = obj.do_sync_task(std::bind(numbered_task, task_number)); | |
std::cout << "task " << task_number << " の結果: " << r << std::endl; | |
task_number++; | |
} | |
} | |
std::cout << " ( ゚д゚)ポカーン" << std::endl; | |
std::cout << "notify_all 停止命令送信" << std::endl; | |
waiter.notify_all(); | |
obj.kill(); | |
std::cout << "join 停止待ち" << std::endl; | |
th.join(); | |
std::cout << "プログラムを終了します" << std::endl; | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment