1212#include < beman/execution/detail/join_env.hpp>
1313#include < beman/execution/detail/inplace_stop_source.hpp>
1414#include < beman/execution/detail/just.hpp>
15+ #include < beman/execution/detail/then.hpp>
1516#include < test/execution.hpp>
1617#include < concepts>
1718
@@ -32,20 +33,40 @@ static_assert(test_detail::queryable<env>);
3233struct non_sender {};
3334static_assert (not test_std::sender<non_sender>);
3435
36+ template <typename ... T>
3537struct sender {
36- using sender_concept = test_std::sender_t ;
37- using completion_signatures = test_std::completion_signatures<test_std::set_value_t (), test_std::set_stopped_t ()>;
38+ using sender_concept = test_std::sender_t ;
39+ using completion_signatures =
40+ test_std::completion_signatures<test_std::set_value_t (T...), test_std::set_stopped_t ()>;
41+
42+ struct state_base {
43+ virtual ~state_base () = default ;
44+ virtual auto complete (T...) -> void = 0;
45+ };
3846 template <test_std::receiver Rcvr>
39- auto connect (Rcvr&& rcvr) {
40- return test_std::connect (test_std::just (), ::std::forward<Rcvr>(rcvr));
47+ struct state : state_base {
48+ using operation_state_concept = test_std::operation_state_t ;
49+ std::remove_cvref_t <Rcvr> rcvr;
50+ state_base** handle{};
51+ auto complete (T... a) -> void override { test_std::set_value (std::move (this ->rcvr ), a...); }
52+ state (auto && r, state_base** h) : rcvr(std::forward<decltype (r)>(r)), handle(h) {}
53+ auto start () & noexcept { *this ->handle = this ; }
54+ };
55+ state_base** handle{nullptr };
56+ template <test_std::receiver Rcvr>
57+ auto connect (Rcvr&& rcvr) -> state<Rcvr> {
58+ return state<Rcvr>(std::forward<Rcvr>(rcvr), this ->handle );
4159 }
4260};
43- static_assert (test_std::sender<sender>);
61+ static_assert (test_std::sender<sender<>>);
62+ static_assert (test_std::sender<sender<int >>);
63+ static_assert (test_std::sender<sender<int , bool >>);
4464
4565template <bool Noexcept>
4666struct token {
47- auto try_associate () -> bool { return {}; }
48- auto disassociate () noexcept (Noexcept) -> void {}
67+ std::size_t * count{nullptr };
68+ auto try_associate () -> bool { return this ->count && bool (++*this ->count ); }
69+ auto disassociate () noexcept (Noexcept) -> void { --*this ->count ; }
4970 template <test_std::sender Sender>
5071 auto wrap (Sender&& sender) -> Sender {
5172 return std::forward<Sender>(sender);
@@ -226,7 +247,7 @@ static_assert(test_std::sender<alloc_sender>);
226247auto test_get_allocator () {
227248 {
228249 alloc_env ae{87 };
229- auto [alloc, ev] = test_detail::spawn_future_get_allocator (sender{}, ae);
250+ auto [alloc, ev] = test_detail::spawn_future_get_allocator (sender<> {}, ae);
230251 static_assert (std::same_as<decltype (alloc), allocator>);
231252 ASSERT (alloc == allocator{87 });
232253 static_assert (std::same_as<decltype (ev), alloc_env>);
@@ -259,7 +280,7 @@ auto test_get_allocator() {
259280 ASSERT (test_std::get_stop_token (ev) == source.get_token ());
260281 }
261282 {
262- auto [alloc, ev] = test_detail::spawn_future_get_allocator (sender{}, env{42 });
283+ auto [alloc, ev] = test_detail::spawn_future_get_allocator (sender<> {}, env{42 });
263284 static_assert (std::same_as<decltype (alloc), std::allocator<void >>);
264285 static_assert (std::same_as<decltype (ev), env>);
265286 ASSERT (ev == env{42 });
@@ -275,13 +296,104 @@ struct rcvr {
275296};
276297static_assert (test_std::receiver<rcvr>);
277298
278- template <test_std::sender Sndr, test_std::async_scope_token Tok, typename Ev>
279- auto test_spawn_future (Sndr&& sndr, Tok&& tok, Ev&& ev) {
280- auto sender{test_std::spawn_future (std::forward<Sndr>(sndr), std::forward<Tok>(tok), std::forward<Ev>(ev))};
281- static_assert (test_std::sender<decltype (sender)>);
282- auto state (test_std::connect (std::move (sender), rcvr{}));
283- static_assert (test_std::operation_state<decltype (state)>);
284- test_std::start (state);
299+ auto test_spawn_future () {
300+ {
301+ std::size_t count{};
302+ sender<int >::state_base* handle{};
303+ int result{};
304+ ASSERT (count == 0u );
305+ ASSERT (handle == nullptr );
306+ ASSERT (result == 0 );
307+
308+ auto sndr{test_std::spawn_future (
309+ sender<int >{&handle} | test_std::then ([](int v) { return v; }), token<true >{&count}, env{})};
310+ ASSERT (count == 1u );
311+ ASSERT (handle != nullptr );
312+ ASSERT (result == 0 );
313+
314+ {
315+ auto state (test_std::connect (std::move (sndr) | test_std::then ([&result](int v) { result = v; }), rcvr{}));
316+ ASSERT (result == 0 );
317+
318+ test_std::start (state);
319+ ASSERT (count == 1u );
320+ ASSERT (result == 0 );
321+
322+ handle->complete (42 );
323+ ASSERT (result == 42 );
324+ ASSERT (count == 1u );
325+ }
326+ ASSERT (count == 0u );
327+ }
328+ {
329+ std::size_t count{};
330+ sender<int >::state_base* handle{};
331+ int result{};
332+ ASSERT (count == 0u );
333+ ASSERT (handle == nullptr );
334+ ASSERT (result == 0 );
335+
336+ auto sndr{test_std::spawn_future (
337+ sender<int >{&handle} | test_std::then ([](int v) { return v; }), token<true >{&count}, env{})};
338+ ASSERT (count == 1u );
339+ ASSERT (handle != nullptr );
340+ ASSERT (result == 0 );
341+
342+ {
343+ auto state (test_std::connect (std::move (sndr) | test_std::then ([&result](int v) { result = v; }), rcvr{}));
344+ ASSERT (result == 0 );
345+
346+ handle->complete (42 );
347+ ASSERT (result == 0 );
348+
349+ test_std::start (state);
350+
351+ ASSERT (result == 42 );
352+ ASSERT (count == 1u );
353+ }
354+ ASSERT (count == 0u );
355+ }
356+ {
357+ std::size_t count{};
358+ sender<int >::state_base* handle{};
359+ int result{};
360+ ASSERT (count == 0u );
361+ ASSERT (handle == nullptr );
362+ ASSERT (result == 0 );
363+
364+ {
365+ auto sndr{test_std::spawn_future (
366+ sender<int >{&handle} | test_std::then ([](int v) { return v; }), token<true >{&count}, env{})};
367+ ASSERT (count == 1u );
368+ ASSERT (handle != nullptr );
369+ ASSERT (result == 0 );
370+ }
371+ ASSERT (count == 1u );
372+ handle->complete (17 );
373+ ASSERT (count == 0u );
374+ ASSERT (result == 0 );
375+ }
376+ {
377+ std::size_t count{};
378+ sender<int >::state_base* handle{};
379+ int result{};
380+ ASSERT (count == 0u );
381+ ASSERT (handle == nullptr );
382+ ASSERT (result == 0 );
383+
384+ {
385+ auto sndr{test_std::spawn_future (
386+ sender<int >{&handle} | test_std::then ([](int v) { return v; }), token<true >{&count}, env{})};
387+ ASSERT (count == 1u );
388+ ASSERT (handle != nullptr );
389+ ASSERT (result == 0 );
390+
391+ handle->complete (17 );
392+ ASSERT (result == 0 );
393+ }
394+ ASSERT (count == 0u );
395+ ASSERT (result == 0 );
396+ }
285397}
286398
287399} // namespace
@@ -299,5 +411,5 @@ TEST(exec_spawn_future) {
299411
300412 test_get_allocator ();
301413
302- test_spawn_future (sender{}, token< true >{}, env{} );
414+ test_spawn_future ();
303415}
0 commit comments