Skip to content

Instantly share code, notes, and snippets.

@sithhell
Created January 11, 2018 14:03
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 sithhell/7c63a3dd79bbe29c5fd7f623ad920b96 to your computer and use it in GitHub Desktop.
Save sithhell/7c63a3dd79bbe29c5fd7f623ad920b96 to your computer and use it in GitHub Desktop.
#include <experimental/coroutine>
#include <iostream>
namespace hpx
{
enum class thread_state : std::uint8_t
{
initialized = 0x00,
pending = 0x01,
active = 0x02,
suspended = 0x04,
terminated = 0x08,
invalid = 0x10
};
struct scheduler;
struct scheduler_promise
{
using handle = std::experimental::coroutine_handle<scheduler_promise>;
scheduler get_return_object();
auto initial_suspend()
{
return std::experimental::suspend_always{};
}
auto final_suspend()
{
return std::experimental::suspend_always{};
}
void unhandled_exception()
{
std::terminate();
}
void return_void()
{
}
};
struct task;
task *next_task = nullptr;
struct task_promise
{
using handle = std::experimental::coroutine_handle<task_promise>;
task get_return_object();
auto initial_suspend()
{
return std::experimental::suspend_always{};
}
auto final_suspend()
{
next_task = nullptr;
return std::experimental::suspend_always{};
}
void unhandled_exception()
{
std::terminate();
}
void return_void()
{
}
};
struct task
{
using promise_type = task_promise;
using handle = promise_type::handle;
task(handle h)
: yield_(false),
handle_(h)
{}
bool await_ready() const
{
// std::cout << "await ready...\n";
return false;
}
void await_suspend(std::experimental::coroutine_handle<> coro) const
{
// std::cout << "await suspend...\n";
}
void await_resume()
{
// std::cout << "await resume...\n";
if (!yield_)
{
handle_.resume();
}
}
bool yield_;
handle handle_;
scheduler_promise::handle scheduler_handle_;
};
struct scheduler
{
using promise_type = scheduler_promise;
using handle = promise_type::handle;
static bool running;
static scheduler create()
{
// main scheduling loop goes here ...
while (running || next_task)
{
if (next_task)
{
std::cout << "scheduling task: " << next_task << '\n';
co_await *next_task;
}
}
co_return;
}
void run()
{
while (handle_ && !handle_.done())
{
handle_.resume();
}
}
handle handle_;
};
bool scheduler::running = true;
scheduler scheduler_promise::get_return_object()
{
return scheduler{handle::from_promise(*this)};
};
task task_promise::get_return_object()
{
// std::cout << "get return object...\n";
return task{handle::from_promise(*this)};
};
template <typename F>
task create_task(F && f)
{
std::forward<F>(f)();
co_return;
}
}
#include <array>
int main()
{
auto s = hpx::scheduler::create();
auto t = hpx::create_task([]()
{
std::cout << "yay\n";
// equivalent to hpx::this_thread::yield()
hpx::next_task->yield_ = true;
hpx::next_task->scheduler_handle_.resume();
hpx::next_task->yield_ = false;
// hpx::this_thread::yield() end
std::cout << "once more ...\n";
// stopping scheduling loop...
hpx::scheduler::running = false;
}
);
t.scheduler_handle_ = s.handle_;
hpx::next_task = &t;
s.run();
}
[
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment