1313 */
1414#include < cassert>
1515#include < chrono>
16+ #include < future>
1617#include < iostream>
18+ #include < memory>
1719#include < optional>
1820#include < thread>
1921#include < tuple>
@@ -29,7 +31,7 @@ using vix::async::core::task;
2931using vix::async::core::when_all;
3032using vix::async::core::when_any;
3133
32- // Helpers: drive a scheduler loop while awaiting a task
34+ // Helpers: run scheduler loop in background
3335struct scheduler_runner
3436{
3537 scheduler &sched;
@@ -50,57 +52,50 @@ struct scheduler_runner
5052 }
5153};
5254
55+ // sync_wait for task<T> that is scheduler-driven (no manual resume!)
5356template <typename T>
54- static T sync_await ( task<T> t)
57+ static T sync_wait (scheduler &sched, task<T> t)
5558{
56- struct runner
57- {
58- task<T> inner;
59- std::optional<T> value;
59+ auto p = std::make_shared<std::promise<T>>();
60+ auto fut = p->get_future ();
6061
61- task<void > run ()
62+ auto wrapper = [p, inner = std::move (t)]() mutable -> task<void >
63+ {
64+ try
6265 {
63- value = co_await inner;
64- co_return ;
66+ if constexpr (std::is_void_v<T>)
67+ {
68+ co_await inner;
69+ p->set_value ();
70+ }
71+ else
72+ {
73+ T v = co_await inner;
74+ p->set_value (std::move (v));
75+ }
6576 }
66- };
67-
68- runner r{std::move (t), std::nullopt };
69- auto top = r.run ();
70- auto h = top.handle ();
71- assert (h);
72-
73- while (!h.done ())
74- h.resume ();
75-
76- assert (r.value .has_value ());
77- return std::move (*r.value );
78- }
79-
80- static void sync_await (task<void > t)
81- {
82- struct runner
83- {
84- task<void > inner;
85-
86- task<void > run ()
77+ catch (...)
8778 {
88- co_await inner;
89- co_return ;
79+ p->set_exception (std::current_exception ());
9080 }
81+ co_return ;
9182 };
9283
93- runner r{std::move (t)};
94- auto top = r.run ();
95- auto h = top.handle ();
96- assert (h);
84+ // start wrapper on the scheduler thread
85+ std::move (wrapper ()).start (sched);
9786
98- while (!h.done ())
99- h.resume ();
87+ if constexpr (std::is_void_v<T>)
88+ {
89+ fut.get ();
90+ return ;
91+ }
92+ else
93+ {
94+ return fut.get ();
95+ }
10096}
10197
102- // when_any compatibility helpers:
103- // support tuple<optional<T>...> and tuple<T...>
98+ // when_any compatibility helpers
10499template <typename X>
105100static bool is_ready (const X &x)
106101{
@@ -231,10 +226,10 @@ int main()
231226 scheduler sched;
232227 scheduler_runner run{sched};
233228
234- sync_await ( test_when_all_basic (sched));
235- sync_await ( test_when_all_mixed_timing (sched));
236- sync_await ( test_when_any_picks_first (sched));
237- sync_await ( test_when_any_handles_immediate (sched));
229+ sync_wait< void >(sched, test_when_all_basic (sched));
230+ sync_wait< void >(sched, test_when_all_mixed_timing (sched));
231+ sync_wait< void >(sched, test_when_any_picks_first (sched));
232+ sync_wait< void >(sched, test_when_any_handles_immediate (sched));
238233
239234 std::cout << " async_when_smoke: OK\n " ;
240235 return 0 ;
0 commit comments