Skip to content

Instantly share code, notes, and snippets.

@Preetam
Last active September 7, 2015 03:28
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Preetam/7844f32f65fd7e1d8819 to your computer and use it in GitHub Desktop.
Save Preetam/7844f32f65fd7e1d8819 to your computer and use it in GitHub Desktop.
#include <future>
#include <functional>
#include <memory>
#include <chrono>
class abstract_task {
public:
virtual bool ready() = 0;
virtual void operator()() = 0;
virtual ~abstract_task() {};
};
template<class T>
class waiting_task : abstract_task
{
public:
using future_ptr = std::unique_ptr<std::future<T>>;
using task_ptr = std::unique_ptr<std::packaged_task<void(future_ptr)>>;
future_ptr fut;
task_ptr _task;
waiting_task(future_ptr fut, task_ptr task)
: fut(std::move(fut)), _task(std::move(task))
{
}
bool
ready() {
auto status = fut->wait_for(std::chrono::seconds(0));
if (status == std::future_status::ready) {
return true;
}
return false;
}
void
operator()() {
(*_task)(std::move(fut));
}
};
class packaged_task : public abstract_task
{
private:
std::unique_ptr<std::packaged_task<void()>> _task;
public:
packaged_task(std::unique_ptr<std::packaged_task<void()>> task)
: _task(std::move(task))
{
}
bool
ready() {
return true;
}
void
operator()() {
(*_task)();
}
};
// g++ -std=c++14 -o taskpool taskpool.cc -lpthread
// ./taskpool
#include <iostream>
#include <functional>
#include <future>
#include <thread>
#include <chrono>
#include <mutex>
#include <queue>
#include <memory>
#include <atomic>
#include "task.hpp"
class taskpool {
public:
template<typename T> using task_t = std::packaged_task<T>;
template<typename T> using task_uptr = std::unique_ptr<task_t<T>>;
std::atomic_bool quit;
std::queue<task_uptr<void()>> tasks;
std::mutex task_list_mutex;
std::unique_ptr<std::thread> runner;
void
add_task(task_uptr<void()> task) {
std::lock_guard<std::mutex> lock(task_list_mutex);
tasks.push(std::move(task));
}
task_uptr<void()>
get_task() {
std::lock_guard<std::mutex> lock(task_list_mutex);
if (tasks.size() == 0) {
return nullptr;
}
auto task_ptr = std::move(tasks.front());
tasks.pop();
return task_ptr;
}
void
run() {
quit = false;
using namespace std::literals;
runner = std::move(std::make_unique<std::thread>([this](){
while (true) {
if (quit) {
return;
}
auto taskptr = get_task();
if (taskptr) {
(*taskptr)();
} else {
std::this_thread::sleep_for(100us);
}
}
}));
}
void
join() {
runner->join();
}
};
void
printer() {
std::cout << "printer()" << std::endl;
}
void
slow_function() {
using namespace std::literals;
std::cout << "starting slow function" << std::endl;
std::this_thread::sleep_for(0.5s);
std::cout << "finished slow function" << std::endl;
}
int
main() {
auto pool = std::make_shared<taskpool>();
pool->run();
pool->add_task(std::make_unique<std::packaged_task<void()>>(printer));
auto slow_task = std::make_unique<std::packaged_task<void()>>(slow_function);
auto slow_task_future_ptr = std::make_unique<std::future<void>>((*slow_task).get_future());
pool->add_task(std::move(slow_task));
auto printer_task = std::make_unique<std::packaged_task<void()>>(printer);
std::unique_ptr<abstract_task> abs_task = std::make_unique<packaged_task>(std::move(printer_task));
if (abs_task->ready()) {
(*abs_task)();
}
auto slow_function_callback = std::make_unique<
std::packaged_task<
void(std::unique_ptr<std::future<void>>)
>
>([pool](std::unique_ptr<std::future<void>> fut) {
std::cout << "slow_function_callback()" << std::endl;
pool->quit = true;
pool->join();
});
waiting_task<void> waits_for_slow_task(std::move(slow_task_future_ptr), std::move(slow_function_callback));
while (!waits_for_slow_task.ready()) {
}
waits_for_slow_task();
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment