xref: /llvm-project/clang/test/CodeGenCoroutines/Inputs/coroutine.h (revision bf5f2354fa6e3f31a1acea75a229fee54359e279)
1 // This is a mock file for <coroutine>.
2 #pragma once
3 
4 namespace std {
5 
6 template <typename R, typename...> struct coroutine_traits {
7   using promise_type = typename R::promise_type;
8 };
9 
10 template <typename Promise = void> struct coroutine_handle;
11 
12 template <> struct coroutine_handle<void> {
13   static coroutine_handle from_address(void *addr) noexcept {
14     coroutine_handle me;
15     me.ptr = addr;
16     return me;
17   }
18   void operator()() { resume(); }
19   void *address() const noexcept { return ptr; }
20   void resume() const { __builtin_coro_resume(ptr); }
21   void destroy() const { __builtin_coro_destroy(ptr); }
22   bool done() const { return __builtin_coro_done(ptr); }
23   coroutine_handle &operator=(decltype(nullptr)) {
24     ptr = nullptr;
25     return *this;
26   }
27   coroutine_handle(decltype(nullptr)) : ptr(nullptr) {}
28   coroutine_handle() : ptr(nullptr) {}
29 //  void reset() { ptr = nullptr; } // add to P0057?
30   explicit operator bool() const { return ptr; }
31 
32 protected:
33   void *ptr;
34 };
35 
36 template <typename Promise> struct coroutine_handle : coroutine_handle<> {
37   using coroutine_handle<>::operator=;
38 
39   static coroutine_handle from_address(void *addr) noexcept {
40     coroutine_handle me;
41     me.ptr = addr;
42     return me;
43   }
44 
45   Promise &promise() const {
46     return *reinterpret_cast<Promise *>(
47         __builtin_coro_promise(ptr, alignof(Promise), false));
48   }
49   static coroutine_handle from_promise(Promise &promise) {
50     coroutine_handle p;
51     p.ptr = __builtin_coro_promise(&promise, alignof(Promise), true);
52     return p;
53   }
54 };
55 
56 template <typename _PromiseT>
57 bool operator==(coroutine_handle<_PromiseT> const &_Left,
58                 coroutine_handle<_PromiseT> const &_Right) noexcept {
59   return _Left.address() == _Right.address();
60 }
61 
62 template <typename _PromiseT>
63 bool operator!=(coroutine_handle<_PromiseT> const &_Left,
64                 coroutine_handle<_PromiseT> const &_Right) noexcept {
65   return !(_Left == _Right);
66 }
67 
68 struct noop_coroutine_promise {};
69 
70 template <>
71 struct coroutine_handle<noop_coroutine_promise> {
72   operator coroutine_handle<>() const noexcept {
73     return coroutine_handle<>::from_address(address());
74   }
75 
76   constexpr explicit operator bool() const noexcept { return true; }
77   constexpr bool done() const noexcept { return false; }
78 
79   constexpr void operator()() const noexcept {}
80   constexpr void resume() const noexcept {}
81   constexpr void destroy() const noexcept {}
82 
83   noop_coroutine_promise &promise() const noexcept {
84     return *static_cast<noop_coroutine_promise *>(
85         __builtin_coro_promise(this->__handle_, alignof(noop_coroutine_promise), false));
86   }
87 
88   constexpr void *address() const noexcept { return __handle_; }
89 
90 private:
91   friend coroutine_handle<noop_coroutine_promise> noop_coroutine() noexcept;
92 
93   coroutine_handle() noexcept {
94     this->__handle_ = __builtin_coro_noop();
95   }
96 
97   void *__handle_ = nullptr;
98 };
99 
100 using noop_coroutine_handle = coroutine_handle<noop_coroutine_promise>;
101 
102 inline noop_coroutine_handle noop_coroutine() noexcept { return noop_coroutine_handle(); }
103 
104 struct suspend_always {
105   bool await_ready() noexcept { return false; }
106   void await_suspend(coroutine_handle<>) noexcept {}
107   void await_resume() noexcept {}
108 };
109 struct suspend_never {
110   bool await_ready() noexcept { return true; }
111   void await_suspend(coroutine_handle<>) noexcept {}
112   void await_resume() noexcept {}
113 };
114 
115 } // namespace std
116