Skip to content

Instantly share code, notes, and snippets.

@alibitek
Forked from kikairoya/taskqueue.cpp
Created December 6, 2012 20:46
Show Gist options
  • Save alibitek/4228185 to your computer and use it in GitHub Desktop.
Save alibitek/4228185 to your computer and use it in GitHub Desktop.
#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