Browse Source

按照

ISO/IEC JTC1 SC22 WG21 N4860
(Date: 2020-03-31)
标准为clang实现coroutine头文件
tags/2.9.10
tearshark 4 years ago
parent
commit
11f1df9a11
2 changed files with 61 additions and 55 deletions
  1. 2
    0
      librf/src/unix/clang_builtin.h
  2. 59
    55
      librf/src/unix/coroutine.h

+ 2
- 0
librf/src/unix/clang_builtin.h View File

@@ -28,9 +28,11 @@ extern "C" void* __builtin_coro_promise(void* addr, int alignment, bool from_pro

extern "C" size_t __builtin_coro_size();
extern "C" void* __builtin_coro_frame();
extern "C" void* __builtin_coro_noop();
extern "C" void* __builtin_coro_free(void* coro_frame);
#pragma intrinsic(__builtin_coro_size)
#pragma intrinsic(__builtin_coro_frame)
#pragma intrinsic(__builtin_coro_noop)
#pragma intrinsic(__builtin_coro_free)

extern "C" void* __builtin_coro_id(int align, void* promise, void* fnaddr, void* parts);

+ 59
- 55
librf/src/unix/coroutine.h View File

@@ -52,6 +52,7 @@ template <class P> struct hash<coroutine_handle<P>>;
#include <memory> // for hash<T*>
#include <cstddef>
#include <cassert>
#include <compare>

#if defined(__clang__)
#include "clang_builtin.h"
@@ -80,17 +81,21 @@ namespace std {
using promise_type = typename _Tp::promise_type;
};

// 17.12.2, coroutine traits
template <typename _Ret, typename... _Args>
struct coroutine_traits : public __coroutine_traits_sfinae<_Ret>
{
};

// 17.12.3, coroutine handle
template <typename _Promise = void>
class coroutine_handle;

template <>
class coroutine_handle<void> {
class coroutine_handle<void>
{
public:
// 17.12.3.1, construct/reset
constexpr coroutine_handle() noexcept : __handle_(nullptr) {}
constexpr coroutine_handle(nullptr_t) noexcept : __handle_(nullptr) {}
coroutine_handle& operator=(nullptr_t) noexcept {
@@ -98,28 +103,15 @@ namespace std {
return *this;
}

// 17.12.3.2, export/import
constexpr void* address() const noexcept { return __handle_; }
constexpr explicit operator bool() const noexcept { return __handle_; }

void operator()() { resume(); }
void resume() {
__builtin_coro_resume(__handle_);
}
void destroy() {
__builtin_coro_destroy(__handle_);
}
bool done() const {
return __builtin_coro_done(__handle_);
}
public:
static coroutine_handle from_address(void* __addr) noexcept {
static constexpr coroutine_handle from_address(void* __addr) noexcept {
coroutine_handle __tmp;
__tmp.__handle_ = __addr;
return __tmp;
}

// FIXME: Should from_address(nullptr) be allowed?
static coroutine_handle from_address(nullptr_t) noexcept {
static constexpr coroutine_handle from_address(nullptr_t) noexcept {
return coroutine_handle(nullptr);
}

@@ -130,6 +122,22 @@ namespace std {
"non-void pointers");
}

// 17.12.3.3, observers
constexpr explicit operator bool() const noexcept {
return __handle_ != nullptr;
}
bool done() const {
return __builtin_coro_done(__handle_);
}

// 17.12.3.4, resumption
void operator()() const { resume(); }
void resume() const {
__builtin_coro_resume(__handle_);
}
void destroy() const{
__builtin_coro_destroy(__handle_);
}
private:
bool __is_suspended() const noexcept {
// FIXME actually implement a check for if the coro is suspended.
@@ -142,50 +150,35 @@ namespace std {
void* __handle_;
};

// 18.11.2.7 comparison operators:
inline bool operator==(coroutine_handle<> __x, coroutine_handle<> __y) noexcept {
// 17.12.3.6, comparison operators
constexpr bool operator==(coroutine_handle<> __x, coroutine_handle<> __y) noexcept {
return __x.address() == __y.address();
}
inline bool operator!=(coroutine_handle<> __x, coroutine_handle<> __y) noexcept {
return !(__x == __y);
}
inline bool operator<(coroutine_handle<> __x, coroutine_handle<> __y) noexcept {
return less<void*>()(__x.address(), __y.address());
}
inline bool operator>(coroutine_handle<> __x, coroutine_handle<> __y) noexcept {
return __y < __x;
}
inline bool operator<=(coroutine_handle<> __x, coroutine_handle<> __y) noexcept {
return !(__x > __y);
}
inline bool operator>=(coroutine_handle<> __x, coroutine_handle<> __y) noexcept {
return !(__x < __y);
constexpr strong_ordering operator<=>(coroutine_handle<> __x, coroutine_handle<> __y) noexcept {
return __x.address() <=> __y.address();
}

template <typename _Promise>
class coroutine_handle : public coroutine_handle<> {
class coroutine_handle : public coroutine_handle<>
{
using _Base = coroutine_handle<>;
public:
#ifndef _LIBCPP_CXX03_LANG
// 18.11.2.1 construct/reset
// 17.12.3.1, construct/reset
using coroutine_handle<>::coroutine_handle;
#else
coroutine_handle() noexcept : _Base() {}
coroutine_handle(nullptr_t) noexcept : _Base(nullptr) {}
#endif

coroutine_handle& operator=(nullptr_t) noexcept {
_Base::operator=(nullptr);
return *this;
}

// 17.12.3.5, promise access
_Promise& promise() const {
return *static_cast<_Promise*>(
__builtin_coro_promise(this->__handle_, alignof(_Promise), false));
}

public:
static coroutine_handle from_address(void* __addr) noexcept {
// 17.12.3.2, export/import
static constexpr coroutine_handle from_address(void* __addr) noexcept {
coroutine_handle __tmp;
__tmp.__handle_ = __addr;
return __tmp;
@@ -195,7 +188,7 @@ namespace std {
// the deleted _Promise* overload doesn't make from_address(nullptr)
// ambiguous.
// FIXME: should from_address work with nullptr?
static coroutine_handle from_address(nullptr_t) noexcept {
static constexpr coroutine_handle from_address(nullptr_t) noexcept {
return coroutine_handle(nullptr);
}

@@ -223,23 +216,32 @@ namespace std {
}
};

// 17.12.4, no-op coroutines
#if __has_builtin(__builtin_coro_noop)
struct noop_coroutine_promise {};

template <>
class coroutine_handle<noop_coroutine_promise>
: public coroutine_handle<> {
class coroutine_handle<noop_coroutine_promise> : public coroutine_handle<>
{
using _Base = coroutine_handle<>;
using _Promise = noop_coroutine_promise;
public:
_Promise& promise() const {
// 17.12.4.2.3, promise access
_Promise& promise() const noexcept {
return *static_cast<_Promise*>(
__builtin_coro_promise(this->__handle_, alignof(_Promise), false));
}
// 17.12.4.2.4, address
constexpr void* address() const noexcept {
return this->__handle_;
}

// 17.12.4.2.1, observers
constexpr explicit operator bool() const noexcept { return true; }
constexpr bool done() const noexcept { return false; }

// 17.12.4.2.2, resumption
constexpr void operator()() const noexcept {}
constexpr void resume() const noexcept {}
constexpr void destroy() const noexcept {}
@@ -251,28 +253,30 @@ namespace std {
};

using noop_coroutine_handle = coroutine_handle<noop_coroutine_promise>;
inline noop_coroutine_handle noop_coroutine() noexcept {
return noop_coroutine_handle();
}
#endif // __has_builtin(__builtin_coro_noop)

// 17.12.5, trivial awaitables
struct suspend_never {
bool await_ready() const noexcept { return true; }
void await_suspend(coroutine_handle<>) const noexcept {}
void await_resume() const noexcept {}
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 {
bool await_ready() const noexcept { return false; }
void await_suspend(coroutine_handle<>) const noexcept {}
void await_resume() const noexcept {}
constexpr bool await_ready() const noexcept { return false; }
constexpr void await_suspend(coroutine_handle<>) const noexcept {}
constexpr void await_resume() const noexcept {}
};

}

// 17.12.3.7, hash support
template <class _Tp>
struct hash<experimental::coroutine_handle<_Tp> > {
using argument_type = experimental::coroutine_handle<_Tp>;
using result_type = size_t;
using __arg_type = experimental::coroutine_handle<_Tp>;
size_t operator()(__arg_type const& __v) const noexcept
{

Loading…
Cancel
Save