Commit 1369f985 authored by Xavier Thompson's avatar Xavier Thompson

Allow co_awaiting anything

parent a5f699f1
#include <typon/typon.hpp> #include <typon/typon.hpp>
#include <typon/logger.hpp> #include <typon/logger.hpp>
#include <python/builtins.hpp>
#include <typon/generator.hpp>
using namespace typon; using namespace typon;
...@@ -12,7 +10,7 @@ int fibo(int n) { ...@@ -12,7 +10,7 @@ int fibo(int n) {
} }
Task<void> hello(int id) { Task<void> hello(int id) {
int n = fibo(20); int n = fibo(40);
LOG("hello(%d), fibo(20) = %d", id, n); LOG("hello(%d), fibo(20) = %d", id, n);
co_return; co_return;
} }
......
...@@ -23,6 +23,7 @@ Task<void> with_lock(int id) ...@@ -23,6 +23,7 @@ Task<void> with_lock(int id)
LOG("with_lock(%d), acquired", id); LOG("with_lock(%d), acquired", id);
int n = fibo(N); int n = fibo(N);
LOG("with_lock(%d), fibo(%d) = %d", id, N, n); LOG("with_lock(%d), fibo(%d) = %d", id, N, n);
LOG("with_lock(%d), releasing", id);
} }
LOG("with_lock(%d), released", id); LOG("with_lock(%d), released", id);
} }
......
...@@ -30,7 +30,9 @@ namespace typon ...@@ -30,7 +30,9 @@ namespace typon
Fork(std::coroutine_handle<promise_type> coroutine) noexcept Fork(std::coroutine_handle<promise_type> coroutine) noexcept
: _coroutine(coroutine) : _coroutine(coroutine)
{} {
static_assert(meta::Awaitable<Fork>);
}
Fork(const Fork &) = delete; Fork(const Fork &) = delete;
Fork& operator=(const Fork &) = delete; Fork& operator=(const Fork &) = delete;
......
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
#include <cstdint> #include <cstdint>
#include <utility> #include <utility>
#include <typon/meta.hpp>
#include <typon/result.hpp> #include <typon/result.hpp>
#include <typon/scheduler.hpp> #include <typon/scheduler.hpp>
#include <typon/stack.hpp> #include <typon/stack.hpp>
......
...@@ -24,7 +24,9 @@ namespace typon ...@@ -24,7 +24,9 @@ namespace typon
coroutine_type _coroutine; coroutine_type _coroutine;
Join(coroutine_type coroutine) noexcept : _coroutine(coroutine) {} Join(coroutine_type coroutine) noexcept : _coroutine(coroutine) {
static_assert(meta::Awaitable<Join>);
}
Join(const Join &) = delete; Join(const Join &) = delete;
Join & operator=(const Join &) = delete; Join & operator=(const Join &) = delete;
...@@ -73,12 +75,19 @@ namespace typon ...@@ -73,12 +75,19 @@ namespace typon
_span.set_sequential_exception(std::current_exception()); _span.set_sequential_exception(std::current_exception());
} }
template <typename U> template <meta::Awaitable U>
decltype(auto) await_transform(U && expr) noexcept decltype(auto) await_transform(U && expr) noexcept
{ {
return std::forward<U>(expr); return std::forward<U>(expr);
} }
template <typename U>
requires (! meta::Awaitable<U>)
decltype(auto) await_transform(U && expr) noexcept
{
return meta::AwaitReady{std::forward<U>(expr)};
}
auto await_transform(Sync &&) noexcept auto await_transform(Sync &&) noexcept
{ {
struct awaitable struct awaitable
......
#ifndef TYPON_META_HPP_INCLUDED #ifndef TYPON_META_HPP_INCLUDED
#define TYPON_META_HPP_INCLUDED #define TYPON_META_HPP_INCLUDED
#include <coroutine>
#include <type_traits>
namespace typon::meta namespace typon::meta
{ {
struct Empty {}; struct Empty {};
template <typename T>
concept Awaiter = requires (T && a, std::coroutine_handle<void> h)
{
// simplified
a.await_ready();
a.await_suspend(h);
a.await_resume();
};
template <typename T>
concept Awaitable = Awaiter<std::remove_cvref_t<T>> || requires (T && a)
{
// simplified
std::forward<T>(a).operator co_await();
};
template <typename T>
requires (! Awaitable<T>)
struct AwaitReady : std::suspend_never {
T _ready;
AwaitReady() = delete;
AwaitReady(const AwaitReady &) = delete;
AwaitReady & operator=(const AwaitReady &) = delete;
AwaitReady(T && ready) : _ready(std::move(ready)) {}
AwaitReady(const T & ready) : _ready(ready) {}
T await_resume() noexcept {
return std::move(_ready);
}
};
} }
......
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
#include <coroutine> #include <coroutine>
#include <utility> #include <utility>
#include <typon/meta.hpp>
#include <typon/result.hpp> #include <typon/result.hpp>
...@@ -17,7 +18,9 @@ namespace typon ...@@ -17,7 +18,9 @@ namespace typon
std::coroutine_handle<promise_type> _coroutine; std::coroutine_handle<promise_type> _coroutine;
Task(std::coroutine_handle<promise_type> coroutine) noexcept : _coroutine(coroutine) {} Task(std::coroutine_handle<promise_type> coroutine) noexcept : _coroutine(coroutine) {
static_assert(meta::Awaitable<Task>);
}
Task(const Task &) = delete; Task(const Task &) = delete;
Task & operator=(const Task &) = delete; Task & operator=(const Task &) = delete;
...@@ -54,6 +57,19 @@ namespace typon ...@@ -54,6 +57,19 @@ namespace typon
return {}; return {};
} }
template <meta::Awaitable U>
decltype(auto) await_transform(U && expr) noexcept
{
return std::forward<U>(expr);
}
template <typename U>
requires (! meta::Awaitable<U>)
decltype(auto) await_transform(U && expr) noexcept
{
return meta::AwaitReady{std::forward<U>(expr)};
}
auto final_suspend() noexcept auto final_suspend() noexcept
{ {
struct awaitable : std::suspend_always struct awaitable : std::suspend_always
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment