1010#include < boost/capy/concept/io_awaitable.hpp>
1111#include < boost/capy/detail/await_suspend_helper.hpp>
1212#include < boost/capy/ex/io_env.hpp>
13+ #include < boost/capy/ex/run_async.hpp>
1314#include < boost/capy/ex/thread_pool.hpp>
1415#include < boost/capy/io_result.hpp>
16+ #include < boost/capy/task.hpp>
17+ #include < boost/capy/test/run_blocking.hpp>
1518
1619#include " test/unit/test_helpers.hpp"
1720
@@ -45,10 +48,7 @@ struct frame_cb_test
4548 cb.destroy = +[](detail::frame_cb*) {};
4649 cb.data = &called;
4750
48- auto h = std::coroutine_handle<>::from_address (
49- static_cast <void *>(&cb));
50-
51- h.resume ();
51+ cb.resume (&cb);
5252 BOOST_TEST (called);
5353 }
5454
@@ -63,10 +63,7 @@ struct frame_cb_test
6363 };
6464 cb.data = &destroy_called;
6565
66- auto h = std::coroutine_handle<>::from_address (
67- static_cast <void *>(&cb));
68-
69- h.destroy ();
66+ cb.destroy (&cb);
7067 BOOST_TEST (destroy_called);
7168 }
7269
@@ -81,133 +78,105 @@ struct frame_cb_test
8178 cb.destroy = +[](detail::frame_cb*) {};
8279 cb.data = &value;
8380
84- auto h = std::coroutine_handle<>::from_address (
85- static_cast <void *>(&cb));
86-
87- h.resume ();
81+ cb.resume (&cb);
8882 BOOST_TEST_EQ (value, 42 );
8983 }
9084
91- void
92- testWithIoAwaitable ()
85+ // IoAwaitable that resumes synchronously and returns a value
86+ struct sync_awaitable
9387 {
94- struct test_awaitable
95- {
96- int * result;
97-
98- bool await_ready () const noexcept
99- {
100- return false ;
101- }
102-
103- std::coroutine_handle<>
104- await_suspend (
105- std::coroutine_handle<> h,
106- io_env const *) noexcept
107- {
108- h.resume ();
109- return std::noop_coroutine ();
110- }
111-
112- io_result<> await_resume () noexcept
113- {
114- *result = 99 ;
115- return {};
116- }
117- };
118-
119- static_assert (IoAwaitable<test_awaitable>);
120-
121- int result = 0 ;
122- bool resumed = false ;
88+ int value;
12389
124- struct state
90+ bool await_ready () const noexcept
12591 {
126- test_awaitable* aw;
127- bool * resumed;
128- };
129-
130- state st{nullptr , &resumed};
131- test_awaitable aw{&result};
132- st.aw = &aw;
92+ return false ;
93+ }
13394
134- detail::frame_cb cb;
135- cb.resume = +[](detail::frame_cb* p) {
136- auto * s = static_cast <state*>(p->data );
137- (void )s->aw ->await_resume ();
138- *s->resumed = true ;
139- };
140- cb.destroy = +[](detail::frame_cb*) {};
141- cb.data = &st;
95+ std::coroutine_handle<>
96+ await_suspend (
97+ std::coroutine_handle<> h,
98+ io_env const *) noexcept
99+ {
100+ return h;
101+ }
142102
143- int dispatch_count = 0 ;
144- test_executor ex (dispatch_count);
145- io_env env{ex, {}};
103+ io_result<int > await_resume () noexcept
104+ {
105+ return {std::error_code{}, value};
106+ }
107+ };
146108
147- auto h = std::coroutine_handle<>::from_address (
148- static_cast <void *>(&cb));
109+ static_assert (IoAwaitable<sync_awaitable>);
149110
150- detail::call_await_suspend (&aw, h, &env);
111+ static task<int >
112+ await_sync (int v)
113+ {
114+ auto [ec, result] = co_await sync_awaitable{v};
115+ co_return result;
116+ }
151117
152- BOOST_TEST (resumed);
118+ void
119+ testWithIoAwaitable ()
120+ {
121+ int result = 0 ;
122+ test::run_blocking (
123+ [&](int v) { result = v; })(
124+ await_sync (99 ));
153125 BOOST_TEST_EQ (result, 99 );
154126 }
155127
156- void
157- testWithAsyncAwaitable ()
128+ // IoAwaitable that posts to executor (async resume)
129+ struct async_awaitable
158130 {
159- thread_pool pool (1 );
160- std::latch done (1 );
161- bool resumed = false ;
131+ int value;
162132
163- struct state
133+ bool await_ready () const noexcept
164134 {
165- bool * resumed;
166- std::latch* done;
167- };
135+ return false ;
136+ }
168137
169- state st{&resumed, &done};
170-
171- detail::frame_cb cb;
172- cb.resume = +[](detail::frame_cb* p) {
173- auto * s = static_cast <state*>(p->data );
174- *s->resumed = true ;
175- s->done ->count_down ();
176- };
177- cb.destroy = +[](detail::frame_cb*) {};
178- cb.data = &st;
138+ std::coroutine_handle<>
139+ await_suspend (
140+ std::coroutine_handle<> h,
141+ io_env const * env) noexcept
142+ {
143+ env->executor .post (h);
144+ return std::noop_coroutine ();
145+ }
179146
180- struct post_awaitable
147+ io_result< int > await_resume () noexcept
181148 {
182- bool await_ready () const noexcept
183- {
184- return false ;
185- }
186-
187- std::coroutine_handle<>
188- await_suspend (
189- std::coroutine_handle<> h,
190- io_env const * env) noexcept
191- {
192- env->executor .post (h);
193- return std::noop_coroutine ();
194- }
195-
196- void await_resume () noexcept {}
197- };
149+ return {std::error_code{}, value};
150+ }
151+ };
198152
199- static_assert (IoAwaitable<post_awaitable >);
153+ static_assert (IoAwaitable<async_awaitable >);
200154
201- post_awaitable aw;
202- io_env env{pool.get_executor (), {}};
155+ static task<int >
156+ await_async (int v)
157+ {
158+ auto [ec, result] = co_await async_awaitable{v};
159+ co_return result;
160+ }
203161
204- auto h = std::coroutine_handle<>::from_address (
205- static_cast <void *>(&cb));
162+ void
163+ testWithAsyncAwaitable ()
164+ {
165+ thread_pool pool (1 );
166+ std::latch done (1 );
167+ int result = 0 ;
206168
207- detail::call_await_suspend (&aw, h, &env);
169+ run_async (pool.get_executor (),
170+ [&](int v) {
171+ result = v;
172+ done.count_down ();
173+ },
174+ [&](std::exception_ptr) {
175+ done.count_down ();
176+ })(await_async (99 ));
208177
209178 done.wait ();
210- BOOST_TEST (resumed );
179+ BOOST_TEST_EQ (result, 99 );
211180 }
212181
213182 void
0 commit comments