YACLib
C++ library for concurrent tasks execution
Loading...
Searching...
No Matches
await_awaiter.hpp
Go to the documentation of this file.
1#pragma once
2
9
10namespace yaclib::detail {
11
13 explicit TransferAwaiter(BaseCore& caller) noexcept : _caller{caller} {
14 YACLIB_ASSERT(caller.Empty());
15 }
16
17 constexpr bool await_ready() const noexcept {
18 return false;
19 }
20
21 template <typename Promise>
22 YACLIB_INLINE auto await_suspend(yaclib_std::coroutine_handle<Promise> handle) noexcept {
23 _caller.StoreCallback(handle.promise());
24 auto* next = MoveToCaller(&_caller.core);
25#if YACLIB_SYMMETRIC_TRANSFER != 0
26 return next->Next(handle.promise());
27#else
28 return Loop(&handle.promise(), next);
29#endif
30 }
31
32 constexpr void await_resume() const noexcept {
33 }
34
35 private:
36 UniqueHandle _caller;
37};
38
39template <typename V, typename E>
41 explicit TransferSingleAwaiter(UniqueCorePtr<V, E>&& result) noexcept : _result{std::move(result)} {
42 YACLIB_ASSERT(_result != nullptr);
43 YACLIB_ASSERT(_result->Empty());
44 }
45
46 constexpr bool await_ready() const noexcept {
47 return false;
48 }
49
50 template <typename Promise>
51 YACLIB_INLINE auto await_suspend(yaclib_std::coroutine_handle<Promise> handle) noexcept {
52 _result->StoreCallback(handle.promise());
53 auto* next = MoveToCaller(_result.Get());
54#if YACLIB_SYMMETRIC_TRANSFER != 0
55 return next->Next(handle.promise());
56#else
57 return Loop(&handle.promise(), next);
58#endif
59 }
60
61 auto await_resume() {
62 return std::move(_result->Get()).Ok();
63 }
64
65 private:
66 UniqueCorePtr<V, E> _result;
67};
68
69template <typename Handle>
71 explicit AwaitAwaiter(Handle caller) noexcept : _caller{caller} {
72 }
73
74 YACLIB_INLINE bool await_ready() const noexcept {
75 return !_caller.core.Empty();
76 }
77
78 template <typename Promise>
79 YACLIB_INLINE bool await_suspend(yaclib_std::coroutine_handle<Promise> handle) noexcept {
80 return _caller.SetCallback(handle.promise());
81 }
82
83 constexpr void await_resume() const noexcept {
84 }
85
86 private:
87 Handle _caller;
88};
89
90class AwaitEvent : public InlineCore, public AtomicCounter<NopeBase, NopeDeleter> {
91 public:
92 using AtomicCounter<NopeBase, NopeDeleter>::AtomicCounter;
93
94 static constexpr auto kShared = false;
95
97 return *this;
98 }
99
100 private:
101 template <bool SymmetricTransfer>
102 [[nodiscard]] YACLIB_INLINE auto Impl(InlineCore& caller) noexcept {
103 if (this->SubEqual(1)) {
104 auto* curr = static_cast<InlineCore*>(next);
105 if constexpr (SymmetricTransfer) {
106 return Step<true>(caller, *curr);
107 } else {
108 curr = curr->Here(caller);
109 YACLIB_ASSERT(curr == nullptr);
110 }
111 }
113 }
114
115 public:
116 [[nodiscard]] InlineCore* Here(InlineCore& caller) noexcept final {
117 return Impl<false>(caller);
118 }
119
120#if YACLIB_SYMMETRIC_TRANSFER != 0
121 [[nodiscard]] yaclib_std::coroutine_handle<> Next(InlineCore& caller) noexcept final {
122 return Impl<true>(caller);
123 }
124#endif
125};
126
127template <typename Event>
129 public:
130 static constexpr auto kShared = Event::kShared;
131
132 template <typename... Handles>
133 explicit MultiAwaitAwaiter(Handles... handles) noexcept : Event{sizeof...(handles) + 1} {
134 SetCallbacksStatic(*this, handles...);
135 }
136
137 template <typename It>
138 explicit MultiAwaitAwaiter(It it, std::size_t count) noexcept : Event{count + 1} {
139 SetCallbacksDynamic(*this, it, count);
140 }
141
143 return this->Get(std::memory_order_acquire) == 1;
144 }
145
146 template <typename Promise>
147 YACLIB_INLINE bool await_suspend(yaclib_std::coroutine_handle<Promise> handle) noexcept {
148 this->next = &handle.promise();
149 return !this->SubEqual(1);
150 }
151
152 constexpr void await_resume() const noexcept {
153 }
154};
155
156template <bool Shared, typename V, typename E>
158
159template <typename V, typename E>
161 public:
162 explicit AwaitSingleAwaiter(UniqueCorePtr<V, E>&& result) noexcept : _result{std::move(result)} {
163 YACLIB_ASSERT(_result != nullptr);
164 }
165
166 YACLIB_INLINE bool await_ready() const noexcept {
167 return !_result->Empty();
168 }
169
170 template <typename Promise>
171 YACLIB_INLINE bool await_suspend(yaclib_std::coroutine_handle<Promise> handle) noexcept {
172 return _result->SetCallback(handle.promise());
173 }
174
176 return std::move(_result->Get()).Ok();
177 }
178
179 private:
180 UniqueCorePtr<V, E> _result;
181};
182
183// TODO(ocelaiwo): different overloads for lvalue and rvalue
184template <typename V, typename E>
186 public:
187 explicit AwaitSingleAwaiter(SharedCorePtr<V, E> result) noexcept : _result{std::move(result)} {
188 YACLIB_ASSERT(_result != nullptr);
189 }
190
191 YACLIB_INLINE bool await_ready() const noexcept {
192 return !_result->Empty();
193 }
194
195 template <typename Promise>
196 YACLIB_INLINE bool await_suspend(yaclib_std::coroutine_handle<Promise> handle) const noexcept {
197 return _result->SetCallback(handle.promise());
198 }
199
200 auto await_resume() const {
201 return std::as_const(_result->Get()).Ok();
202 }
203
204 private:
205 SharedCorePtr<V, E> _result;
206};
207
208} // namespace yaclib::detail
A intrusive pointer to objects with an embedded reference count.
InlineCore * Here(InlineCore &caller) noexcept final
static constexpr auto kShared
AwaitEvent & GetCall() noexcept
AwaitSingleAwaiter(UniqueCorePtr< V, E > &&result) noexcept
YACLIB_INLINE bool await_suspend(yaclib_std::coroutine_handle< Promise > handle) noexcept
YACLIB_INLINE bool await_ready() const noexcept
YACLIB_INLINE bool await_suspend(yaclib_std::coroutine_handle< Promise > handle) const noexcept
YACLIB_INLINE bool await_ready() const noexcept
AwaitSingleAwaiter(SharedCorePtr< V, E > result) noexcept
YACLIB_INLINE bool await_suspend(yaclib_std::coroutine_handle< Promise > handle) noexcept
MultiAwaitAwaiter(Handles... handles) noexcept
MultiAwaitAwaiter(It it, std::size_t count) noexcept
constexpr void await_resume() const noexcept
YACLIB_INLINE bool await_ready() const noexcept
#define YACLIB_ASSERT(cond)
Definition log.hpp:85
YACLIB_INLINE BaseCore * MoveToCaller(BaseCore *head) noexcept
Definition core.hpp:94
void SetCallbacksStatic(Event &event, Handles... handles)
YACLIB_INLINE void Loop(InlineCore *prev, InlineCore *curr) noexcept
void SetCallbacksDynamic(Event &event, It it, std::size_t count)
Contract< V, E > MakeContract()
Creates related future and promise.
Definition contract.hpp:25
YACLIB_INLINE bool SubEqual(std::size_t n) noexcept
constexpr void await_resume() const noexcept
AwaitAwaiter(Handle caller) noexcept
YACLIB_INLINE bool await_suspend(yaclib_std::coroutine_handle< Promise > handle) noexcept
YACLIB_INLINE bool await_ready() const noexcept
constexpr bool await_ready() const noexcept
constexpr void await_resume() const noexcept
TransferAwaiter(BaseCore &caller) noexcept
YACLIB_INLINE auto await_suspend(yaclib_std::coroutine_handle< Promise > handle) noexcept
YACLIB_INLINE auto await_suspend(yaclib_std::coroutine_handle< Promise > handle) noexcept
TransferSingleAwaiter(UniqueCorePtr< V, E > &&result) noexcept
constexpr bool await_ready() const noexcept