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