Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-03 08:13:17

0001 //===----------------------------------------------------------------------===//
0002 //
0003 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
0004 // See https://llvm.org/LICENSE.txt for license information.
0005 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
0006 //
0007 //===----------------------------------------------------------------------===//
0008 
0009 #ifndef _LIBCPP___COROUTINE_COROUTINE_HANDLE_H
0010 #define _LIBCPP___COROUTINE_COROUTINE_HANDLE_H
0011 
0012 #include <__assert>
0013 #include <__config>
0014 #include <__cstddef/nullptr_t.h>
0015 #include <__cstddef/size_t.h>
0016 #include <__functional/hash.h>
0017 #include <__memory/addressof.h>
0018 #include <__type_traits/remove_cv.h>
0019 #include <compare>
0020 
0021 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
0022 #  pragma GCC system_header
0023 #endif
0024 
0025 #if _LIBCPP_STD_VER >= 20
0026 
0027 _LIBCPP_BEGIN_NAMESPACE_STD
0028 
0029 // [coroutine.handle]
0030 template <class _Promise = void>
0031 struct _LIBCPP_TEMPLATE_VIS coroutine_handle;
0032 
0033 template <>
0034 struct _LIBCPP_TEMPLATE_VIS coroutine_handle<void> {
0035 public:
0036   // [coroutine.handle.con], construct/reset
0037   constexpr coroutine_handle() noexcept = default;
0038 
0039   _LIBCPP_HIDE_FROM_ABI constexpr coroutine_handle(nullptr_t) noexcept {}
0040 
0041   _LIBCPP_HIDE_FROM_ABI coroutine_handle& operator=(nullptr_t) noexcept {
0042     __handle_ = nullptr;
0043     return *this;
0044   }
0045 
0046   // [coroutine.handle.export.import], export/import
0047   _LIBCPP_HIDE_FROM_ABI constexpr void* address() const noexcept { return __handle_; }
0048 
0049   _LIBCPP_HIDE_FROM_ABI static constexpr coroutine_handle from_address(void* __addr) noexcept {
0050     coroutine_handle __tmp;
0051     __tmp.__handle_ = __addr;
0052     return __tmp;
0053   }
0054 
0055   // [coroutine.handle.observers], observers
0056   _LIBCPP_HIDE_FROM_ABI constexpr explicit operator bool() const noexcept { return __handle_ != nullptr; }
0057 
0058   _LIBCPP_HIDE_FROM_ABI bool done() const {
0059     _LIBCPP_ASSERT_VALID_EXTERNAL_API_CALL(__is_suspended(), "done() can be called only on suspended coroutines");
0060     return __builtin_coro_done(__handle_);
0061   }
0062 
0063   // [coroutine.handle.resumption], resumption
0064   _LIBCPP_HIDE_FROM_ABI void operator()() const { resume(); }
0065 
0066   _LIBCPP_HIDE_FROM_ABI void resume() const {
0067     _LIBCPP_ASSERT_VALID_EXTERNAL_API_CALL(__is_suspended(), "resume() can be called only on suspended coroutines");
0068     _LIBCPP_ASSERT_VALID_EXTERNAL_API_CALL(!done(), "resume() has undefined behavior when the coroutine is done");
0069     __builtin_coro_resume(__handle_);
0070   }
0071 
0072   _LIBCPP_HIDE_FROM_ABI void destroy() const {
0073     _LIBCPP_ASSERT_VALID_EXTERNAL_API_CALL(__is_suspended(), "destroy() can be called only on suspended coroutines");
0074     __builtin_coro_destroy(__handle_);
0075   }
0076 
0077 private:
0078   _LIBCPP_HIDE_FROM_ABI bool __is_suspended() const {
0079     // FIXME actually implement a check for if the coro is suspended.
0080     return __handle_ != nullptr;
0081   }
0082 
0083   void* __handle_ = nullptr;
0084 };
0085 
0086 // [coroutine.handle.compare]
0087 inline _LIBCPP_HIDE_FROM_ABI constexpr bool operator==(coroutine_handle<> __x, coroutine_handle<> __y) noexcept {
0088   return __x.address() == __y.address();
0089 }
0090 inline _LIBCPP_HIDE_FROM_ABI constexpr strong_ordering
0091 operator<=>(coroutine_handle<> __x, coroutine_handle<> __y) noexcept {
0092   return compare_three_way()(__x.address(), __y.address());
0093 }
0094 
0095 template <class _Promise>
0096 struct _LIBCPP_TEMPLATE_VIS coroutine_handle {
0097 public:
0098   // [coroutine.handle.con], construct/reset
0099   constexpr coroutine_handle() noexcept = default;
0100 
0101   _LIBCPP_HIDE_FROM_ABI constexpr coroutine_handle(nullptr_t) noexcept {}
0102 
0103   _LIBCPP_HIDE_FROM_ABI static coroutine_handle from_promise(_Promise& __promise) {
0104     using _RawPromise = __remove_cv_t<_Promise>;
0105     coroutine_handle __tmp;
0106     __tmp.__handle_ =
0107         __builtin_coro_promise(std::addressof(const_cast<_RawPromise&>(__promise)), alignof(_Promise), true);
0108     return __tmp;
0109   }
0110 
0111   _LIBCPP_HIDE_FROM_ABI coroutine_handle& operator=(nullptr_t) noexcept {
0112     __handle_ = nullptr;
0113     return *this;
0114   }
0115 
0116   // [coroutine.handle.export.import], export/import
0117   _LIBCPP_HIDE_FROM_ABI constexpr void* address() const noexcept { return __handle_; }
0118 
0119   _LIBCPP_HIDE_FROM_ABI static constexpr coroutine_handle from_address(void* __addr) noexcept {
0120     coroutine_handle __tmp;
0121     __tmp.__handle_ = __addr;
0122     return __tmp;
0123   }
0124 
0125   // [coroutine.handle.conv], conversion
0126   _LIBCPP_HIDE_FROM_ABI constexpr operator coroutine_handle<>() const noexcept {
0127     return coroutine_handle<>::from_address(address());
0128   }
0129 
0130   // [coroutine.handle.observers], observers
0131   _LIBCPP_HIDE_FROM_ABI constexpr explicit operator bool() const noexcept { return __handle_ != nullptr; }
0132 
0133   _LIBCPP_HIDE_FROM_ABI bool done() const {
0134     _LIBCPP_ASSERT_VALID_EXTERNAL_API_CALL(__is_suspended(), "done() can be called only on suspended coroutines");
0135     return __builtin_coro_done(__handle_);
0136   }
0137 
0138   // [coroutine.handle.resumption], resumption
0139   _LIBCPP_HIDE_FROM_ABI void operator()() const { resume(); }
0140 
0141   _LIBCPP_HIDE_FROM_ABI void resume() const {
0142     _LIBCPP_ASSERT_VALID_EXTERNAL_API_CALL(__is_suspended(), "resume() can be called only on suspended coroutines");
0143     _LIBCPP_ASSERT_VALID_EXTERNAL_API_CALL(!done(), "resume() has undefined behavior when the coroutine is done");
0144     __builtin_coro_resume(__handle_);
0145   }
0146 
0147   _LIBCPP_HIDE_FROM_ABI void destroy() const {
0148     _LIBCPP_ASSERT_VALID_EXTERNAL_API_CALL(__is_suspended(), "destroy() can be called only on suspended coroutines");
0149     __builtin_coro_destroy(__handle_);
0150   }
0151 
0152   // [coroutine.handle.promise], promise access
0153   _LIBCPP_HIDE_FROM_ABI _Promise& promise() const {
0154     return *static_cast<_Promise*>(__builtin_coro_promise(this->__handle_, alignof(_Promise), false));
0155   }
0156 
0157 private:
0158   _LIBCPP_HIDE_FROM_ABI bool __is_suspended() const {
0159     // FIXME actually implement a check for if the coro is suspended.
0160     return __handle_ != nullptr;
0161   }
0162   void* __handle_ = nullptr;
0163 };
0164 
0165 // [coroutine.handle.hash]
0166 template <class _Tp>
0167 struct hash<coroutine_handle<_Tp>> {
0168   _LIBCPP_HIDE_FROM_ABI size_t operator()(const coroutine_handle<_Tp>& __v) const noexcept {
0169     return hash<void*>()(__v.address());
0170   }
0171 };
0172 
0173 _LIBCPP_END_NAMESPACE_STD
0174 
0175 #endif // __LIBCPP_STD_VER >= 20
0176 
0177 #endif // _LIBCPP___COROUTINE_COROUTINE_HANDLE_H