@@ -297,11 +297,12 @@ struct _sndr<Predecessor, Successor>::type {
297
297
constructible_from<
298
298
Successor,
299
299
Successor2>) //
300
- explicit type(Predecessor2&& predecessor, Successor2&& successor) noexcept (
300
+ explicit type(Predecessor2&& predecessor, Successor2&& successor, instruction_ptr returnAddress ) noexcept (
301
301
std::is_nothrow_constructible_v<Predecessor, Predecessor2> &&
302
302
std::is_nothrow_constructible_v<Successor, Successor2>)
303
303
: predecessor_(static_cast <Predecessor&&>(predecessor))
304
- , successor_(static_cast <Successor&&>(successor)) {}
304
+ , successor_(static_cast <Successor&&>(successor))
305
+ , returnAddress_(returnAddress) {}
305
306
306
307
friend constexpr blocking_kind tag_invoke (tag_t <blocking>, const type& self) {
307
308
blocking_kind pred = blocking (self.predecessor_ );
@@ -311,6 +312,11 @@ struct _sndr<Predecessor, Successor>::type {
311
312
return std::max (pred (), std::min (succ (), blocking_kind::maybe ()));
312
313
}
313
314
315
+ friend instruction_ptr
316
+ tag_invoke (tag_t <get_return_address>, const type& t) noexcept {
317
+ return t.returnAddress_ ;
318
+ }
319
+
314
320
template (typename Receiver, typename Sender) //
315
321
(requires same_as<remove_cvref_t <Sender>, type> AND
316
322
constructible_from<Successor, member_t <Sender, Successor>> AND
@@ -338,84 +344,123 @@ struct _sndr<Predecessor, Successor>::type {
338
344
private:
339
345
UNIFEX_NO_UNIQUE_ADDRESS Predecessor predecessor_;
340
346
UNIFEX_NO_UNIQUE_ADDRESS Successor successor_;
347
+ instruction_ptr returnAddress_;
341
348
};
342
349
343
350
namespace _cpo {
344
351
struct _fn {
345
- // Sequencing a single sender is just the same as returning the sender
346
- // itself.
347
- template <typename First>
348
- remove_cvref_t <First> operator ()(First&& first) const
349
- noexcept (std::is_nothrow_constructible_v<remove_cvref_t <First>, First>) {
350
- return static_cast <First&&>(first);
351
- }
352
+ private:
353
+ struct _impl_fn {
354
+ // Sequencing a single sender is just the same as returning the sender
355
+ // itself.
356
+ template <typename First>
357
+ remove_cvref_t <First> operator ()(instruction_ptr, First&& first) const
358
+ noexcept (
359
+ std::is_nothrow_constructible_v<remove_cvref_t <First>, First>) {
360
+ return static_cast <First&&>(first);
361
+ }
352
362
353
- template (typename First, typename Second) //
354
- (requires sender<First> AND sender<Second> AND
355
- tag_invocable<_fn, First, Second>) //
356
- auto
357
- operator ()(First&& first, Second&& second) const
358
- noexcept (is_nothrow_tag_invocable_v<_fn, First, Second>)
359
- -> tag_invoke_result_t <_fn, First, Second> {
360
- return unifex::tag_invoke (
361
- _fn{}, static_cast <First&&>(first), static_cast <Second&&>(second));
362
- }
363
+ template (typename First, typename Second) //
364
+ (requires sender<First> AND sender<Second> AND
365
+ tag_invocable<_fn, First, Second>) //
366
+ auto
367
+ operator ()(instruction_ptr, First&& first, Second&& second) const
368
+ noexcept (is_nothrow_tag_invocable_v<_fn, First, Second>)
369
+ -> tag_invoke_result_t <_fn, First, Second> {
370
+ return unifex::tag_invoke (
371
+ _fn{}, static_cast <First&&>(first), static_cast <Second&&>(second));
372
+ }
363
373
364
- template (typename First, typename Second) //
365
- (requires sender<First> AND
366
- sender<Second> AND (!tag_invocable<_fn, First, Second>)) //
367
- auto
368
- operator()(First&& first, Second&& second) const
369
- noexcept (std::is_nothrow_constructible_v<
370
- _seq::_sender<First, Second>,
371
- First,
372
- Second>) -> _seq::_sender<First, Second> {
373
- return _seq::_sender<First, Second>{
374
- static_cast <First&&>(first), static_cast <Second&&>(second)};
375
- }
374
+ template (typename First, typename Second) //
375
+ (requires sender<First> AND
376
+ sender<Second> AND (!tag_invocable<_fn, First, Second>)) //
377
+ auto
378
+ operator()(
379
+ instruction_ptr returnAddress, First&& first, Second&& second) const
380
+ noexcept (std::is_nothrow_constructible_v<
381
+ _seq::_sender<First, Second>,
382
+ First,
383
+ Second,
384
+ instruction_ptr>) -> _seq::_sender<First, Second> {
385
+ return _seq::_sender<First, Second>{
386
+ static_cast <First&&>(first),
387
+ static_cast <Second&&>(second),
388
+ returnAddress};
389
+ }
376
390
377
- template (
378
- typename First, typename Second, typename Third, typename ... Rest) //
379
- (requires sender<First> AND sender<Second> AND
380
- sender<Third> AND (sender<Rest>&&...)
381
- AND tag_invocable<_fn, First, Second, Third, Rest...>) //
382
- auto
383
- operator()(
384
- First&& first, Second&& second, Third&& third, Rest&&... rest) const
385
- noexcept (is_nothrow_tag_invocable_v<_fn, First, Second, Third, Rest...>)
386
- -> tag_invoke_result_t<_fn, First, Second, Third, Rest...> {
387
- return unifex::tag_invoke (
388
- _fn{},
389
- static_cast <First&&>(first),
390
- static_cast <Second&&>(second),
391
- static_cast <Third&&>(third),
392
- static_cast <Rest&&>(rest)...);
393
- }
391
+ template (
392
+ typename First, typename Second, typename Third, typename ... Rest) //
393
+ (requires sender<First> AND sender<Second> AND
394
+ sender<Third> AND (sender<Rest>&&...)
395
+ AND tag_invocable<_fn, First, Second, Third, Rest...>) //
396
+ auto
397
+ operator()(
398
+ instruction_ptr,
399
+ First&& first,
400
+ Second&& second,
401
+ Third&& third,
402
+ Rest&&... rest) const
403
+ noexcept (is_nothrow_tag_invocable_v<_fn, First, Second, Third, Rest...>)
404
+ -> tag_invoke_result_t<_fn, First, Second, Third, Rest...> {
405
+ return unifex::tag_invoke (
406
+ _fn{},
407
+ static_cast <First&&>(first),
408
+ static_cast <Second&&>(second),
409
+ static_cast <Third&&>(third),
410
+ static_cast <Rest&&>(rest)...);
411
+ }
394
412
395
- template (
396
- typename First, typename Second, typename Third, typename ... Rest) //
397
- (requires sender<First> AND sender<Second> AND
398
- sender<Third> AND (sender<Rest>&&...)
399
- AND(!tag_invocable<_fn, First, Second, Third, Rest...>)) //
400
- auto
401
- operator()(First&& first, Second&& second, Third&& third, Rest&&... rest)
402
- const noexcept (
403
- std::is_nothrow_invocable_v<_fn, First, Second> &&
404
- std::is_nothrow_invocable_v<
405
- _fn,
406
- std::invoke_result_t <_fn, First, Second>,
407
- Third,
408
- Rest...>)
409
- -> std::invoke_result_t<
410
- _fn,
411
- std::invoke_result_t<_fn, First, Second>,
412
- Third,
413
- Rest...> {
414
- // Fall-back to pair-wise invocation of the sequence() CPO.
415
- return (*this )(
416
- (*this )(static_cast <First&&>(first), static_cast <Second&&>(second)),
417
- static_cast <Third&&>(third),
418
- static_cast <Rest&&>(rest)...);
413
+ template (
414
+ typename First, typename Second, typename Third, typename ... Rest) //
415
+ (requires sender<First> AND sender<Second> AND
416
+ sender<Third> AND (sender<Rest>&&...)
417
+ AND(!tag_invocable<_fn, First, Second, Third, Rest...>)) //
418
+ auto
419
+ operator()(
420
+ instruction_ptr returnAddress,
421
+ First&& first,
422
+ Second&& second,
423
+ Third&& third,
424
+ Rest&&... rest) const
425
+ noexcept (
426
+ std::is_nothrow_invocable_v<
427
+ _impl_fn,
428
+ instruction_ptr,
429
+ First,
430
+ Second> &&
431
+ std::is_nothrow_invocable_v<
432
+ _impl_fn,
433
+ instruction_ptr,
434
+ std::invoke_result_t <_fn, First, Second>,
435
+ Third,
436
+ Rest...>)
437
+ -> std::invoke_result_t<
438
+ _impl_fn,
439
+ instruction_ptr,
440
+ std::invoke_result_t<_fn, First, Second>,
441
+ Third,
442
+ Rest...> {
443
+ // Fall-back to pair-wise invocation of the sequence() CPO.
444
+ return (*this )(
445
+ returnAddress,
446
+ (*this )(
447
+ returnAddress,
448
+ static_cast <First&&>(first),
449
+ static_cast <Second&&>(second)),
450
+ static_cast <Third&&>(third),
451
+ static_cast <Rest&&>(rest)...);
452
+ }
453
+ };
454
+
455
+ public:
456
+ template <typename First, typename ... Rest>
457
+ auto operator ()(First&& first, Rest&&... rest) const noexcept (
458
+ std::is_nothrow_invocable_v<_impl_fn, instruction_ptr, First, Rest...>)
459
+ -> std::invoke_result_t<_impl_fn, instruction_ptr, First, Rest...> {
460
+ return _impl_fn{}(
461
+ instruction_ptr::read_return_address (),
462
+ std::forward<First>(first),
463
+ std::forward<Rest>(rest)...);
419
464
}
420
465
};
421
466
} // namespace _cpo
0 commit comments