Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

LWG-3460 Unimplementable noop_coroutine_handle guarantees #1452

Merged
merged 8 commits into from
Dec 2, 2020
56 changes: 45 additions & 11 deletions stl/inc/coroutine
Original file line number Diff line number Diff line change
Expand Up @@ -88,13 +88,14 @@ struct coroutine_handle<void> {
__builtin_coro_destroy(_Ptr);
}

protected:
private:
void* _Ptr = nullptr;
};

template <class _Promise>
struct coroutine_handle : coroutine_handle<> {
using coroutine_handle<>::coroutine_handle;
struct coroutine_handle {
constexpr coroutine_handle() noexcept = default;
constexpr coroutine_handle(nullptr_t) noexcept {}

_NODISCARD static coroutine_handle from_promise(_Promise& _Prom) noexcept { // strengthened
const auto _Prom_ptr = const_cast<void*>(static_cast<const volatile void*>(_STD addressof(_Prom)));
Expand All @@ -109,15 +110,46 @@ struct coroutine_handle : coroutine_handle<> {
return *this;
}

_NODISCARD constexpr void* address() const noexcept {
return _Ptr;
}

_NODISCARD static constexpr coroutine_handle from_address(void* const _Addr) noexcept { // strengthened
coroutine_handle _Result;
_Result._Ptr = _Addr;
return _Result;
}

constexpr operator coroutine_handle<>() const noexcept {
return coroutine_handle<>::from_address(_Ptr);
}

constexpr explicit operator bool() const noexcept {
return _Ptr != nullptr;
}

_NODISCARD bool done() const noexcept { // strengthened
return __builtin_coro_done(_Ptr);
}

void operator()() const {
__builtin_coro_resume(_Ptr);
}

void resume() const {
__builtin_coro_resume(_Ptr);
}

void destroy() const noexcept { // strengthened
__builtin_coro_destroy(_Ptr);
}

_NODISCARD _Promise& promise() const noexcept { // strengthened
return *reinterpret_cast<_Promise*>(__builtin_coro_promise(_Ptr, 0, false));
}

private:
void* _Ptr = nullptr;
};

_NODISCARD constexpr bool operator==(const coroutine_handle<> _Left, const coroutine_handle<> _Right) noexcept {
Expand Down Expand Up @@ -145,9 +177,13 @@ struct noop_coroutine_promise {};

// STRUCT coroutine_handle<noop_coroutine_promise>
template <>
struct coroutine_handle<noop_coroutine_promise> : coroutine_handle<> {
struct coroutine_handle<noop_coroutine_promise> {
CaseyCarter marked this conversation as resolved.
Show resolved Hide resolved
friend coroutine_handle noop_coroutine() noexcept;

constexpr operator coroutine_handle<>() const noexcept {
return coroutine_handle<>::from_address(_Ptr);
}

constexpr explicit operator bool() const noexcept {
return true;
}
Expand All @@ -159,17 +195,15 @@ struct coroutine_handle<noop_coroutine_promise> : coroutine_handle<> {
constexpr void resume() const noexcept {}
constexpr void destroy() const noexcept {}

using _Promise = noop_coroutine_promise;

_NODISCARD _Promise& promise() const noexcept {
_NODISCARD noop_coroutine_promise& promise() const noexcept {
// Returns a reference to the associated promise
return *reinterpret_cast<_Promise*>(__builtin_coro_promise(_Ptr, 0, false));
return *reinterpret_cast<noop_coroutine_promise*>(__builtin_coro_promise(_Ptr, 0, false));
}

private:
coroutine_handle() noexcept {
_Ptr = __builtin_coro_noop();
}
coroutine_handle() noexcept = default;

void* _Ptr = __builtin_coro_noop();
};

// ALIAS noop_coroutine_handle
Expand Down