Coroutines are mostly working but they're kind of junk anyway. Feel free to tinker with this if you like.
parent
8d1570f44a
commit
daf9a3cc07
@ -1 +1 @@ |
||||
set makeprg=meson\ compile\ -C\ . |
||||
set makeprg=meson\ compile\ -j\ 4\ -C\ . |
||||
|
@ -0,0 +1,125 @@ |
||||
#include <concepts> |
||||
#include <coroutine> |
||||
#include <exception> |
||||
#include <iostream> |
||||
#include <vector> |
||||
#include <assert.h> |
||||
#include <chrono> |
||||
|
||||
using namespace std; |
||||
using namespace std::chrono; |
||||
|
||||
template<typename T> |
||||
struct Task { |
||||
struct promise_type; |
||||
|
||||
using handle_type = std::coroutine_handle<promise_type>; |
||||
|
||||
struct promise_type { |
||||
T value_; |
||||
std::exception_ptr exception_; |
||||
|
||||
Task get_return_object() { |
||||
return Task(handle_type::from_promise(*this)); |
||||
} |
||||
|
||||
std::suspend_always initial_suspend() { |
||||
return {}; |
||||
} |
||||
|
||||
std::suspend_always final_suspend() noexcept { |
||||
return {}; |
||||
} |
||||
|
||||
void unhandled_exception() { |
||||
exception_ = std::current_exception(); |
||||
} |
||||
|
||||
template<std::convertible_to<T> From> // C++20 concept
|
||||
void return_value(From &&from) { |
||||
value_ = std::forward<From>(from); |
||||
} |
||||
|
||||
template<std::convertible_to<T> From> // C++20 concept
|
||||
std::suspend_always yield_value(From &&from) { |
||||
value_ = std::forward<From>(from); |
||||
return {}; |
||||
} |
||||
|
||||
void return_void() {} |
||||
}; |
||||
|
||||
handle_type h_; |
||||
|
||||
Task() { |
||||
} |
||||
|
||||
Task(handle_type h) : h_(h) { |
||||
} |
||||
|
||||
Task(const Task &t) : h_(t.h_) { |
||||
} |
||||
|
||||
void destroy() { |
||||
h_.destroy(); |
||||
} |
||||
|
||||
T operator()() { |
||||
assert(!h_.done()); |
||||
call(); |
||||
return std::move(h_.promise().value_); |
||||
} |
||||
|
||||
bool done() { |
||||
return h_.done(); |
||||
} |
||||
|
||||
private: |
||||
|
||||
void call() { |
||||
h_(); |
||||
|
||||
if (h_.promise().exception_) |
||||
std::rethrow_exception(h_.promise().exception_); |
||||
} |
||||
}; |
||||
|
||||
#define pass() co_await std::suspend_always{} |
||||
|
||||
Task<unsigned> task_test() |
||||
{ |
||||
pass(); |
||||
|
||||
for (unsigned i = 0; i < 3; ++i) |
||||
co_yield i; |
||||
|
||||
co_return 1000; |
||||
} |
||||
|
||||
int main() |
||||
{ |
||||
|
||||
const int task_count = 4; |
||||
vector<Task<unsigned>> tasks; |
||||
|
||||
for(int i = 0; i < task_count; i++) { |
||||
auto t = task_test(); |
||||
tasks.push_back(std::move(t)); |
||||
} |
||||
|
||||
int done_count = 0; |
||||
while(done_count < task_count) { |
||||
for(int i = 0; i < task_count; i++) { |
||||
Task<unsigned> &t = tasks[i]; |
||||
|
||||
if(t.done()) { |
||||
t.destroy(); |
||||
done_count++; |
||||
} else { |
||||
auto res = t(); |
||||
cout << "T# " << i << " result " |
||||
<< res << endl; |
||||
} |
||||
} |
||||
} |
||||
} |
Loading…
Reference in new issue