|
13 | 13 | #include <concepts> |
14 | 14 | #include <coroutine> |
15 | 15 | #include <exception> |
| 16 | +#include <memory> |
16 | 17 |
|
17 | 18 | namespace boost { |
18 | 19 | namespace capy { |
@@ -160,48 +161,60 @@ struct executor_ref |
160 | 161 |
|
161 | 162 | //---------------------------------------------------------- |
162 | 163 |
|
163 | | -struct async_io_t |
| 164 | +struct socket |
164 | 165 | { |
165 | | - bool await_ready() const noexcept { return false; } |
166 | | - void await_resume() const noexcept {} |
| 166 | + struct async_awaitable |
| 167 | + { |
| 168 | + async_awaitable(socket& s) : s_(s) {} |
| 169 | + bool await_ready() const noexcept { return false; } |
| 170 | + void await_resume() const noexcept {} |
167 | 171 |
|
168 | | - // Affine overload: receives dispatcher from caller |
169 | | - template<class Executor> |
170 | | - void await_suspend(coro h, Executor const& ex) const |
| 172 | + // Affine overload: receives dispatcher from caller |
| 173 | + template<class Executor> |
| 174 | + void await_suspend(coro h, Executor const& ex) const |
| 175 | + { |
| 176 | + s_.perform(h, executor_ref(ex)); |
| 177 | + } |
| 178 | + |
| 179 | + private: |
| 180 | + socket& s_; |
| 181 | + }; |
| 182 | + |
| 183 | + socket() |
| 184 | + : op_(new state) |
| 185 | + { |
| 186 | + } |
| 187 | + |
| 188 | + // Asynchronous operation that wraps OS-level I/O |
| 189 | + async_awaitable async_io() |
171 | 190 | { |
172 | | - auto p = make_state(h, executor_ref(ex)); |
173 | | - ex.post(p); // simulate OS call |
| 191 | + return async_awaitable(*this); |
174 | 192 | } |
175 | 193 |
|
176 | 194 | private: |
177 | | - // this goes in the TU |
178 | | - static work* make_state(coro h, executor_ref ex) |
| 195 | + struct state : work |
179 | 196 | { |
180 | | - struct state : work |
181 | | - { |
182 | | - coro h_; |
183 | | - executor_ref ex_; |
184 | | - state(coro h, executor_ref ex) |
185 | | - : h_(h), ex_(ex) |
186 | | - { |
187 | | - } |
| 197 | + coro h_; |
| 198 | + executor_ref ex_; |
188 | 199 |
|
189 | | - void operator()() override |
190 | | - { |
191 | | - auto h = h_; |
192 | | - auto ex = ex_; |
193 | | - delete this; |
194 | | - ex.dispatch(h); |
195 | | - } |
| 200 | + void operator()() override |
| 201 | + { |
| 202 | + ex_.dispatch(h_); |
| 203 | + } |
196 | 204 |
|
197 | | - // OVERLAPPED, HANDLE, etc |
198 | | - }; |
199 | | - return new state{ h, ex }; |
| 205 | + // OVERLAPPED, HANDLE, etc |
| 206 | + }; |
| 207 | + |
| 208 | + void perform(coro h, executor_ref const& ex) |
| 209 | + { |
| 210 | + op_->h_ = h; |
| 211 | + op_->ex_ = ex; |
| 212 | + ex.post(op_.get()); // simulate OS call |
200 | 213 | } |
| 214 | + |
| 215 | + std::unique_ptr<state> op_; |
201 | 216 | }; |
202 | 217 |
|
203 | | -// Asynchronous operation that wraps OS-level I/O |
204 | | -inline constexpr async_io_t async_io{}; |
205 | 218 |
|
206 | 219 | //---------------------------------------------------------- |
207 | 220 |
|
@@ -420,20 +433,20 @@ void async_run(Executor ex, task t) |
420 | 433 |
|
421 | 434 | //---------------------------------------------------------- |
422 | 435 |
|
423 | | -inline task async_read_some() |
| 436 | +inline task async_read_some(socket& sock) |
424 | 437 | { |
425 | | - co_await async_io; |
| 438 | + co_await sock.async_io(); |
426 | 439 | } |
427 | 440 |
|
428 | | -inline task async_read() |
| 441 | +inline task async_read(socket& sock) |
429 | 442 | { |
430 | | - co_await async_read_some(); |
| 443 | + co_await async_read_some(sock); |
431 | 444 | } |
432 | 445 |
|
433 | | -inline task async_request() |
| 446 | +inline task async_request(socket& sock) |
434 | 447 | { |
435 | 448 | for(int i = 0; i < 100; ++i) |
436 | | - co_await async_read(); |
| 449 | + co_await async_read(sock); |
437 | 450 | } |
438 | 451 |
|
439 | 452 | } // co |
|
0 commit comments