Kernel/include_std/coroutine
2024-11-15 01:54:21 +02:00

190 lines
5.1 KiB
Plaintext

/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
namespace std
{
#if __cpp_impl_coroutine
namespace detail
{
template <class, class...>
struct coroutine_traits_base
{
};
template <class R, class... Args>
requires requires { typename R::promise_type; }
struct coroutine_traits_base<R, Args...>
{
using promise_type = R::promise_type;
};
}
template <class R, class... Args>
struct coroutine_traits : detail::coroutine_traits_base<R, Args...>
{
};
template <class Promise = void>
struct coroutine_handle;
struct noop_coroutine_promise;
template <>
struct coroutine_handle<noop_coroutine_promise>;
using noop_coroutine_handle = coroutine_handle<noop_coroutine_promise>;
noop_coroutine_handle noop_coroutine() noexcept;
template <class T>
struct hash;
template <class P>
struct hash<coroutine_handle<P>>;
template <>
struct coroutine_handle<void>
{
private:
void *ptr;
public:
constexpr coroutine_handle() noexcept : ptr(nullptr) {}
constexpr coroutine_handle(nullptr_t __nul) noexcept : ptr(__nul) {}
coroutine_handle &operator=(nullptr_t) noexcept
{
ptr = nullptr;
return *this;
}
constexpr void *address() const noexcept { return ptr; }
static constexpr coroutine_handle from_address(void *addr)
{
coroutine_handle temp;
temp.ptr = addr;
return temp;
}
constexpr explicit operator bool() const noexcept { return bool(ptr); }
bool done() const { return __builtin_coro_done(ptr); }
void operator()() const { resume(); }
void resume() const { __builtin_coro_resume(ptr); }
void destroy() const { __builtin_coro_destroy(ptr); }
};
constexpr bool operator==(coroutine_handle<> x, coroutine_handle<> y) noexcept
{
return x.address() == y.address();
}
// constexpr strong_ordering operator<=>(coroutine_handle<> x, coroutine_handle<> y) noexcept;
template <class Promise>
struct coroutine_handle
{
private:
void *ptr;
public:
constexpr coroutine_handle() noexcept : ptr(nullptr) {}
constexpr coroutine_handle(nullptr_t) noexcept : ptr(nullptr) {}
static coroutine_handle from_promise(Promise &promise)
{
coroutine_handle temp;
temp.ptr = __builtin_coro_promise((char *)&promise, __alignof(Promise), true);
return temp;
}
coroutine_handle &operator=(nullptr_t) noexcept
{
ptr = nullptr;
return *this;
}
constexpr void *address() const noexcept { return ptr; }
static constexpr coroutine_handle from_address(void *addr)
{
coroutine_handle temp;
temp.ptr = addr;
return temp;
}
constexpr operator coroutine_handle<>() const noexcept
{
return coroutine_handle<>::from_address(address());
}
constexpr explicit operator bool() const noexcept { return bool(ptr); }
bool done() const { return __builtin_coro_done(ptr); }
void operator()() const { resume(); }
void resume() const { __builtin_coro_resume(ptr); }
void destroy() const { __builtin_coro_destroy(ptr); }
Promise &promise() const { return *static_cast<Promise *>(ptr); }
};
struct noop_coroutine_promise
{
};
template <>
struct coroutine_handle<noop_coroutine_promise>
{
private:
static struct __chframe
{
static void __stub_resume() {}
void (*__a)() = __stub_resume;
void (*__b)() = __stub_resume;
struct noop_coroutine_promise __c;
} __frame;
void *ptr = &__frame;
explicit coroutine_handle() noexcept = default;
friend coroutine_handle noop_coroutine() noexcept;
public:
constexpr operator coroutine_handle<>() const noexcept { return coroutine_handle<>::from_address(address()); }
constexpr explicit operator bool() const noexcept { return true; }
constexpr bool done() const noexcept { return false; }
constexpr void operator()() const noexcept {}
constexpr void resume() const noexcept {}
constexpr void destroy() const noexcept {}
noop_coroutine_promise &promise() const noexcept { return __frame.__c; }
constexpr void *address() const noexcept { return ptr; }
};
inline noop_coroutine_handle::__chframe noop_coroutine_handle::__frame{};
noop_coroutine_handle noop_coroutine() noexcept { return noop_coroutine_handle(); }
struct suspend_never
{
constexpr bool await_ready() const noexcept { return true; }
constexpr void await_suspend(coroutine_handle<>) const noexcept {}
constexpr void await_resume() const noexcept {}
};
struct suspend_always
{
constexpr bool await_ready() const noexcept { return false; }
constexpr void await_suspend(coroutine_handle<>) const noexcept {}
constexpr void await_resume() const noexcept {}
};
#else
#error "kernel requires -fcoroutines"
#endif
}