-
-
Save sithhell/7c63a3dd79bbe29c5fd7f623ad920b96 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 <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