Browse Source

按照

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

+ 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);

+ 60
- 91
librf/src/unix/coroutine.h View File

@@ -11,47 +11,13 @@

#define _EXPERIMENTAL_COROUTINE_

/**
experimental/coroutine synopsis

// C++next

namespace std {
namespace experimental {
inline namespace coroutines_v1 {

// 18.11.1 coroutine traits
template <typename R, typename... ArgTypes>
class coroutine_traits;
// 18.11.2 coroutine handle
template <typename Promise = void>
class coroutine_handle;
// 18.11.2.7 comparison operators:
bool operator==(coroutine_handle<> x, coroutine_handle<> y) noexcept;
bool operator!=(coroutine_handle<> x, coroutine_handle<> y) noexcept;
bool operator<(coroutine_handle<> x, coroutine_handle<> y) noexcept;
bool operator<=(coroutine_handle<> x, coroutine_handle<> y) noexcept;
bool operator>=(coroutine_handle<> x, coroutine_handle<> y) noexcept;
bool operator>(coroutine_handle<> x, coroutine_handle<> y) noexcept;
// 18.11.3 trivial awaitables
struct suspend_never;
struct suspend_always;
// 18.11.2.8 hash support:
template <class T> struct hash;
template <class P> struct hash<coroutine_handle<P>>;

} // namespace coroutines_v1
} // namespace experimental
} // namespace std

*/

#include <new>
#include <type_traits>
#include <functional>
#include <memory> // for hash<T*>
#include <cstddef>
#include <cassert>
#include <compare>

#if defined(__clang__)
#include "clang_builtin.h"
@@ -80,17 +46,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 +68,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 +87,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 +115,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 +153,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 +181,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 +218,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> > {
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
{

+ 1
- 1
vs_proj/librf.vcxproj View File

@@ -40,7 +40,7 @@
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<PlatformToolset>v142</PlatformToolset>
<PlatformToolset>ClangCL</PlatformToolset>
<UseDebugLibraries>true</UseDebugLibraries>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">

Loading…
Cancel
Save