@@ -209,6 +209,7 @@ namespace exec {
209209 };
210210
211211 template <tail_sender _TailSender>
212+ requires (!same_as<__null_tail_sender, _TailSender>)
212213 struct maybe_tail_sender {
213214 maybe_tail_sender () noexcept = default ;
214215 maybe_tail_sender (__null_tail_sender) noexcept {}
@@ -313,96 +314,124 @@ namespace exec {
313314 bool valid_;
314315 };
315316
316- template <tail_sender _TailSender, tail_receiver _TailReceiver>
317- auto __start_until_nullable (_TailSender __t , _TailReceiver __r) {
318- if constexpr (__nullable_tail_sender_to<_TailSender, _TailReceiver>) {
319- return __t ;
320- } else if constexpr (__terminal_tail_sender_to<_TailSender, _TailReceiver>) {
321- // restrict scope of op
322- {
323- auto op = stdexec::connect (std::move (__t ), std::move (__r));
324- stdexec::start (op);
317+ namespace __start_until_nullable_ {
318+
319+ struct __start_until_nullable_t ;
320+
321+ template <tail_sender _TailSender, tail_receiver _TailReceiver>
322+ struct __start_until_nullable_result ;
323+
324+ template <class _TailSender , class _TailReceiver >
325+ using __start_until_nullable_result_t = typename __start_until_nullable_result<_TailSender, _TailReceiver>::type;
326+
327+ template <tail_sender _TailSender, tail_receiver _TailReceiver>
328+ struct __start_until_nullable_result {
329+ using type =
330+ __if<
331+ __bool<__nullable_tail_sender_to<_TailSender, _TailReceiver>>, _TailSender,
332+ __if<
333+ __bool<__terminal_tail_sender_to<_TailSender, _TailReceiver>>, __null_tail_sender,
334+ __minvoke<__with_default<__q<__start_until_nullable_result_t >, __null_tail_sender>,
335+ __next_tail_from_sender_to_t <_TailSender, _TailReceiver>,
336+ _TailReceiver>
337+ >
338+ >;
339+ };
340+
341+ struct __start_until_nullable_t {
342+ template <tail_sender _TailSender, tail_receiver _TailReceiver>
343+ auto operator ()(_TailSender __t , _TailReceiver __r) const noexcept
344+ -> __start_until_nullable_result_t<_TailSender, _TailReceiver> {
345+ if constexpr (__nullable_tail_sender_to<_TailSender, _TailReceiver>) {
346+ return __t ;
347+ } else if constexpr (__terminal_tail_sender_to<_TailSender, _TailReceiver>) {
348+ // restrict scope of op
349+ {
350+ auto op = stdexec::connect (std::move (__t ), std::move (__r));
351+ stdexec::start (op);
352+ }
353+ return __null_tail_sender{};
354+ } else {
355+ auto op = stdexec::connect (std::move (__t ), __r);
356+ return __start_until_nullable_t {}(stdexec::start (op), std::move (__r));
357+ }
325358 }
326- return __null_tail_sender{};
327- } else {
328- auto op = stdexec::connect (std::move (__t ), __r);
329- return __start_until_nullable (stdexec::start (op), std::move (__r));
330- }
331- }
359+ };
360+
361+ } // namespace __start_until_nullable_
362+ using __start_until_nullable_::__start_until_nullable_t ;
363+ inline constexpr __start_until_nullable_t __start_until_nullable{};
332364
333- #if 0
334- template <class _Next, class _TailSender, class _TailReceiver, class... _Prev>
335- auto __start_next(_Next next, _TailReceiver r) {
336- if constexpr (__one_of<_Next, _TailSender, _Prev...>) {
365+ template <tail_sender _NextTailSender, tail_sender _TailSender, tail_receiver _TailReceiver, tail_sender... _PrevTailSenders>
366+ auto __start_next (_NextTailSender __next, _TailReceiver __r) {
367+ if constexpr (__one_of<_NextTailSender, _TailSender, _PrevTailSenders...>) {
337368 static_assert (
338- (nullable_tail_sender_to <_TailSender, _TailReceiver> ||
339- (nullable_tail_sender_to<_Prev , _TailReceiver> || ...)),
369+ (__nullable_tail_sender_to <_TailSender, _TailReceiver> ||
370+ (__nullable_tail_sender_to<_PrevTailSenders , _TailReceiver> || ...)),
340371 " At least one tail_sender in a cycle must be nullable to avoid "
341372 " entering an infinite loop" );
342- return __start_until_nullable(next , std::move(r ));
373+ return __start_until_nullable (__next , std::move (__r ));
343374 } else {
344375 using result_type =
345- decltype(__start_sequential(next, r, type_list< _TailSender, _Prev ...>{} ));
346- if constexpr (same_as<result_type, _Next >) {
376+ decltype (__start_sequential<_NextTailSender, _TailReceiver, _TailSender, _PrevTailSenders ...>(__next, __r ));
377+ if constexpr (same_as<result_type, _NextTailSender >) {
347378 // Let the loop in resume_tail_sender() handle checking the boolean.
348- return next ;
379+ return __next ;
349380 } else {
350- return __start_sequential(next, std::move(r), type_list< _TailSender, _Prev ...>{} );
381+ return __start_sequential<_NextTailSender, _TailReceiver, _TailSender, _PrevTailSenders ...>(__next, std::move (__r) );
351382 }
352383 }
353384 }
354385
355- template<tail_sender _TailSender, tail_receiver _TailReceiver, class... _Prev>
356- auto _start_sequential(_TailSender c, _TailReceiver r, type_list<_Prev...>) {
357- static_assert(
358- _tail_sender<_TailSender>, "_start_sequential: must be called with a tail_sender");
359- if constexpr (_terminal_tail_sender_to<_TailSender, _TailReceiver>) {
360- if constexpr (nullable_tail_sender_to<_TailSender, _TailReceiver>) {
386+ template <tail_sender _TailSender, tail_receiver _TailReceiver, class ... _PrevTailSenders>
387+ auto __start_sequential (_TailSender c, _TailReceiver r) {
388+ if constexpr (__terminal_tail_sender_to<_TailSender, _TailReceiver>) {
389+ if constexpr (__nullable_tail_sender_to<_TailSender, _TailReceiver>) {
361390 return c;
362391 } else {
363392 // restrict scope of op
364393 {
365- auto op = unifex ::connect(std::move(c), std::move(r));
366- unifex ::start(op);
394+ auto op = stdexec ::connect (std::move (c), std::move (r));
395+ stdexec ::start (op);
367396 }
368- return null_tail_sender {};
397+ return __null_tail_sender {};
369398 }
370399 } else {
371- using next_t = next_tail_sender_to_t <_TailSender, _TailReceiver>;
372- using result_type = decltype(_start_next <next_t, _TailSender, _TailReceiver, _Prev ...>(
400+ using next_t = __next_tail_from_sender_to_t <_TailSender, _TailReceiver>;
401+ using result_type = decltype (__start_next <next_t , _TailSender, _TailReceiver, _PrevTailSenders ...>(
373402 std::declval<next_t >(), r));
374- if constexpr (std::is_void_v<next_t>) {
375- // restrict scope of op
376- {
377- auto op = unifex::connect(std::move(c), std::move(r));
378- unifex::start(op);
403+ if constexpr (same_as<result_type, next_t >) {
404+ static_assert (__nullable_tail_sender_to<_TailSender, _TailReceiver>, " recursing tail_sender must be nullable" );
405+ auto op = stdexec::connect (std::move (c), std::move (r));
406+ // using result_type = variant_tail_sender<
407+ // __null_tail_sender,
408+ // next_t>;
409+ if (!op) {
410+ return // result_type{
411+ next_t {};// __null_tail_sender{}};
379412 }
380- return null_tail_sender{};
381- } else if constexpr (same_as<result_type, next_t>) {
382- auto op = unifex::connect(std::move(c), std::move(r));
383- return unifex::start(op);
384- } else if constexpr (nullable_tail_sender_to<_TailSender, _TailReceiver>) {
385- auto op = unifex::connect(std::move(c), r);
386- using result_type = variant_tail_sender<
387- null_tail_sender,
388- decltype(_start_next<next_t, _TailSender, _TailReceiver, _Prev...>(
389- unifex::start(op), r))>;
413+ return // result_type{
414+ stdexec::start (op);// };
415+ } else if constexpr (__nullable_tail_sender_to<_TailSender, _TailReceiver>) {
416+ auto op = stdexec::connect (std::move (c), r);
417+ // using result_type = variant_tail_sender<
418+ // __null_tail_sender,
419+ // decltype(_start_next<next_t, _TailSender, _TailReceiver, _PrevTailSenders...>(
420+ // stdexec::start(op), r))>;
421+ // if (!op) {
422+ // return result_type{__null_tail_sender{}};
423+ // }
390424 if (!op) {
391- return result_type{null_tail_sender{}};
425+ return // result_type{
426+ __null_tail_sender{};// };
392427 }
393- return result_type{
394- _start_next <next_t, _TailSender, _TailReceiver, _Prev ...>(unifex ::start(op), r)};
428+ return // result_type{
429+ __start_next <next_t , _TailSender, _TailReceiver, _PrevTailSenders ...>(stdexec ::start (op), r); // };
395430 } else {
396- auto op = unifex ::connect(std::move(c), r);
397- return _start_next <next_t, _TailSender, _TailReceiver, _Prev ...>(unifex ::start(op), r);
431+ auto op = stdexec ::connect (std::move (c), r);
432+ return __start_next <next_t , _TailSender, _TailReceiver, _PrevTailSenders ...>(stdexec ::start (op), r);
398433 }
399434 }
400435 }
401436
402- template<class _TailSender, class _TailReceiver> //
403- auto _start_sequential(_TailSender c, _TailReceiver r) {
404- return _start_sequential(c, r, type_list<>{});
405- }
406- #endif
407-
408437} // namespace exec
0 commit comments