stdexec: update to latest commit
The result of execution::when_all seems to have changed, so I needed
to make a slight change to `sleep_for` to return a task instead of a
Sender.
Signed-off-by: Patrick Williams <patrick@stwcx.xyz>
Change-Id: Ib47c631f8e970838a79ffb44e2a1db4c86a831c4
diff --git a/include/sdbusplus/async/stdexec/__detail/__meta.hpp b/include/sdbusplus/async/stdexec/__detail/__meta.hpp
index 903e1b8..1977521 100644
--- a/include/sdbusplus/async/stdexec/__detail/__meta.hpp
+++ b/include/sdbusplus/async/stdexec/__detail/__meta.hpp
@@ -31,7 +31,7 @@
struct __ignore
{
__ignore() = default;
- __ignore(auto&&) noexcept {}
+ constexpr __ignore(auto&&...) noexcept {}
};
// Before gcc-12, gcc really didn't like tuples or variants of immovable types
@@ -67,30 +67,24 @@
template <class _T>
using __t = typename _T::__t;
-// For hiding a template type parameter from ADL
-template <class _T>
-struct __x_
-{
- using __t = struct __t_
- {
- using __t = _T;
- };
-};
-template <class _T>
-using __x = __t<__x_<_T>>;
-
template <bool _B>
using __bool = std::bool_constant<_B>;
-template <std::size_t _N>
-using __index = std::integral_constant<std::size_t, _N>;
+template <class _Ty>
+struct __mtype
+{
+ using __t = _Ty;
+};
// Some utilities for manipulating lists of types at compile time
template <class...>
struct __types;
template <class _T>
-using __id = _T;
+using __midentity = _T;
+
+template <std::size_t _N>
+using __msize_t = char[_N + 1];
template <class _T>
inline constexpr auto __v = _T::value;
@@ -104,284 +98,87 @@
template <class _T, _T _I>
inline constexpr _T __v<std::integral_constant<_T, _I>> = _I;
+template <std::size_t _I>
+inline constexpr std::size_t __v<char[_I]> = _I - 1;
+
+template <bool>
+struct __i
+{
+ template <template <class...> class _Fn, class... _Args>
+ using __g = _Fn<_Args...>;
+};
+
+template <class...>
+concept __tru = true; // a dependent value
+
+template <template <class...> class _Fn, class... _Args>
+using __meval = typename __i<__tru<_Args...>>::template __g<_Fn, _Args...>;
+
+template <class _Fn, class... _Args>
+using __minvoke = __meval<_Fn::template __f, _Args...>;
+
+template <class _Ty, class... _Args>
+using __make_dependent_on =
+ typename __i<__tru<_Args...>>::template __g<__midentity, _Ty>;
+
template <template <class...> class _Fn>
struct __q
{
template <class... _Args>
- using __f = _Fn<_Args...>;
+ using __f = __meval<_Fn, _Args...>;
};
-template <template <class...> class _Fn>
-struct __q1
-{
- template <class _Arg>
- using __f = _Fn<_Arg>;
-};
-
-template <template <class...> class _Fn>
-struct __q2
-{
- template <class _First, class _Second>
- using __f = _Fn<_First, _Second>;
-};
-
-template <template <class...> class _Fn>
-struct __q3
-{
- template <class _First, class _Second, class _Third>
- using __f = _Fn<_First, _Second, _Third>;
-};
-
-template <template <class...> class _T, std::size_t _Count>
-struct __qN;
-template <template <class...> class _T>
-struct __qN<_T, 1u> : __q1<_T>
-{};
-template <template <class...> class _T>
-struct __qN<_T, 2u> : __q2<_T>
-{};
-template <template <class...> class _T>
-struct __qN<_T, 3u> : __q3<_T>
-{};
-
template <template <class...> class _Fn, class... _Front>
struct __mbind_front_q
{
template <class... _Args>
- using __f = _Fn<_Front..., _Args...>;
-};
-
-template <template <class...> class _Fn, class... _Front>
-struct __mbind_front_q1
-{
- template <class _A>
- using __f = _Fn<_Front..., _A>;
-};
-
-template <template <class...> class _Fn, class... _Front>
-struct __mbind_front_q2
-{
- template <class _A, class _B>
- using __f = _Fn<_Front..., _A, _B>;
-};
-
-template <template <class...> class _Fn, class... _Front>
-struct __mbind_front_q3
-{
- template <class _A, class _B, class _C>
- using __f = _Fn<_Front..., _A, _B, _C>;
+ using __f = __meval<_Fn, _Front..., _Args...>;
};
template <class _Fn, class... _Front>
using __mbind_front = __mbind_front_q<_Fn::template __f, _Front...>;
-template <class _Fn, class... _Front>
-using __mbind_front1 = __mbind_front_q1<_Fn::template __f, _Front...>;
-
-template <class _Fn, class... _Front>
-using __mbind_front2 = __mbind_front_q2<_Fn::template __f, _Front...>;
-
-template <class _Fn, class... _Front>
-using __mbind_front3 = __mbind_front_q3<_Fn::template __f, _Front...>;
-
template <template <class...> class _Fn, class... _Back>
struct __mbind_back_q
{
template <class... _Args>
- using __f = _Fn<_Args..., _Back...>;
-};
-
-template <template <class...> class _Fn, class... _Back>
-struct __mbind_back_q1
-{
- template <class _A>
- using __f = _Fn<_A, _Back...>;
-};
-
-template <template <class...> class _Fn, class... _Back>
-struct __mbind_back_q2
-{
- template <class _A, class _B>
- using __f = _Fn<_A, _B, _Back...>;
-};
-
-template <template <class...> class _Fn, class... _Back>
-struct __mbind_back_q3
-{
- template <class _A, class _B, class _C>
- using __f = _Fn<_A, _B, _C, _Back...>;
+ using __f = __meval<_Fn, _Args..., _Back...>;
};
template <class _Fn, class... _Back>
using __mbind_back = __mbind_back_q<_Fn::template __f, _Back...>;
-template <class _Fn, class... _Back>
-using __mbind_back1 = __mbind_back_q1<_Fn::template __f, _Back...>;
-
-template <class _Fn, class... _Back>
-using __mbind_back2 = __mbind_back_q2<_Fn::template __f, _Back...>;
-
-template <class _Fn, class... _Back>
-using __mbind_back3 = __mbind_back_q3<_Fn::template __f, _Back...>;
-
-template <class _Fn, class... _Args>
-using __minvoke = typename _Fn::template __f<_Args...>;
-
-template <class _Fn, class _First>
-using __minvoke1 = typename _Fn::template __f<_First>;
-
-template <class _Fn, class _First, class _Second>
-using __minvoke2 = typename _Fn::template __f<_First, _Second>;
-
-template <class _Fn, class _First, class _Second, class _Third>
-using __minvoke3 = typename _Fn::template __f<_First, _Second, _Third>;
-
template <template <class...> class _T, class... _Args>
-concept __valid = requires { typename _T<_Args...>; };
-
-template <template <class> class _T, class _First>
-concept __valid1 = requires { typename _T<_First>; };
-
-template <template <class, class> class _T, class _First, class _Second>
-concept __valid2 = requires { typename _T<_First, _Second>; };
-
-template <template <class, class, class> class _T, class _First, class _Second,
- class _Third>
-concept __valid3 = requires { typename _T<_First, _Second, _Third>; };
+concept __valid = requires { typename __meval<_T, _Args...>; };
template <class _Fn, class... _Args>
concept __minvocable = __valid<_Fn::template __f, _Args...>;
-template <class _Fn, class _First>
-concept __minvocable1 = __valid1<_Fn::template __f, _First>;
-
-template <class _Fn, class _First, class _Second>
-concept __minvocable2 = __valid2<_Fn::template __f, _First, _Second>;
-
-template <class _Fn, class _First, class _Second, class _Third>
-concept __minvocable3 = __valid3<_Fn::template __f, _First, _Second, _Third>;
-
-template <bool>
-struct __make_dependent_
-{
- template <class _Ty>
- using __f = _Ty;
-};
-template <class _NonDependent, class _Dependent>
-using __make_dependent_on =
- __minvoke<__make_dependent_<sizeof(__types<_Dependent>*) == 0>,
- _NonDependent>;
-
-template <class _Fn, class _Default, class... _Args>
-struct __with_default_
-{
- using __t = _Default;
-};
-template <class _Fn, class _Default, class... _Args>
- requires __minvocable<_Fn, _Args...>
-struct __with_default_<_Fn, _Default, _Args...>
+template <class _Fn, class... _Args>
+struct __force_minvoke_
{
using __t = __minvoke<_Fn, _Args...>;
};
+template <class _Fn, class... _Args>
+using __force_minvoke = __t<__force_minvoke_<_Fn, _Args...>>;
-template <class _Fn, class _Default>
-struct __with_default
-{
- template <class... _Args>
- using __f = __t<__with_default_<_Fn, _Default, _Args...>>;
-};
-
-template <template <class...> class _T>
-struct __mdefer
-{
- template <class... _Args>
- using __f = __minvoke<__qN<_T, sizeof...(_Args)>, _Args...>;
-};
-
-template <class _T>
-struct __mconst
-{
- template <class...>
- using __f = _T;
-};
-
-template <class _Fn, class _Continuation = __q<__types>>
-struct __transform
-{
- template <class... _Args>
- using __f = __minvoke<_Continuation, __minvoke1<_Fn, _Args>...>;
-};
-
-template <class _Fn, class...>
-struct __fold_right_
+template <class _Fn, class... _Args>
+struct __mdefer_
{};
-template <class _Fn, class _State, class _Head, class... _Tail>
-#if !STDEXEC_NVHPC()
-// BUGBUG find better work-around
- requires __minvocable2<_Fn, _State, _Head>
-#endif
-struct __fold_right_<_Fn, _State, _Head, _Tail...> :
- __fold_right_<_Fn, __minvoke2<_Fn, _State, _Head>, _Tail...>
-{};
-template <class _Fn, class _State>
-struct __fold_right_<_Fn, _State>
+template <class _Fn, class... _Args>
+ requires __minvocable<_Fn, _Args...>
+struct __mdefer_<_Fn, _Args...>
{
- using __t = _State;
+ using __t = __minvoke<_Fn, _Args...>;
};
-
-template <class _Init, class _Fn>
-struct __fold_right
-{
- template <class... _Args>
- using __f = __t<__fold_right_<_Fn, _Init, _Args...>>;
-};
-
-template <class _Continuation, class...>
-struct __concat_
+template <class _Fn, class... _Args>
+struct __mdefer : __mdefer_<_Fn, _Args...>
{};
-template <class _Continuation, class... _As>
- requires(sizeof...(_As) == 0) && __minvocable<_Continuation, _As...>
-struct __concat_<_Continuation, _As...>
-{
- using __t = __minvoke<_Continuation, _As...>;
-};
-template <class _Continuation, template <class...> class _A, class... _As>
- requires __minvocable<_Continuation, _As...>
-struct __concat_<_Continuation, _A<_As...>>
-{
- using __t = __minvoke<_Continuation, _As...>;
-};
-template <class _Continuation, template <class...> class _A, class... _As,
- template <class...> class _B, class... _Bs, class... _Tail>
-struct __concat_<_Continuation, _A<_As...>, _B<_Bs...>, _Tail...> :
- __concat_<_Continuation, __types<_As..., _Bs...>, _Tail...>
-{};
-template <class _Continuation, template <class...> class _A, class... _As,
- template <class...> class _B, class... _Bs,
- template <class...> class _C, class... _Cs, class... _Tail>
-struct __concat_<_Continuation, _A<_As...>, _B<_Bs...>, _C<_Cs...>, _Tail...> :
- __concat_<_Continuation, __types<_As..., _Bs..., _Cs...>, _Tail...>
-{};
-template <class _Continuation, template <class...> class _A, class... _As,
- template <class...> class _B, class... _Bs,
- template <class...> class _C, class... _Cs,
- template <class...> class _D, class... _Ds, class... _Tail>
-struct __concat_<_Continuation, _A<_As...>, _B<_Bs...>, _C<_Cs...>, _D<_Ds...>,
- _Tail...> :
- __concat_<_Continuation, __types<_As..., _Bs..., _Cs..., _Ds...>, _Tail...>
-{};
-
-template <class _Continuation = __q<__types>>
-struct __concat
-{
- template <class... _Args>
- using __f = __t<__concat_<_Continuation, _Args...>>;
-};
template <bool>
struct __if_
{
- template <class _True, class>
+ template <class _True, class...>
using __f = _True;
};
template <>
@@ -391,14 +188,108 @@
using __f = _False;
};
#if STDEXEC_NVHPC()
-template <class _Pred, class _True, class _False>
-using __if = __minvoke2<__if_<_Pred::value>, _True, _False>;
+template <class _Pred, class _True, class... _False>
+ requires(sizeof...(_False) <= 1)
+using __if = __minvoke<__if_<_Pred::value>, _True, _False...>;
#else
-template <class _Pred, class _True, class _False>
-using __if = __minvoke2<__if_<__v<_Pred>>, _True, _False>;
+template <class _Pred, class _True, class... _False>
+ requires(sizeof...(_False) <= 1)
+using __if = __minvoke<__if_<__v<_Pred>>, _True, _False...>;
#endif
-template <bool _Pred, class _True, class _False>
-using __if_c = __minvoke2<__if_<_Pred>, _True, _False>;
+template <bool _Pred, class _True, class... _False>
+ requires(sizeof...(_False) <= 1)
+using __if_c = __minvoke<__if_<_Pred>, _True, _False...>;
+
+template <class _T>
+struct __mconst
+{
+ template <class...>
+ using __f = _T;
+};
+
+template <class _Fn, class _Default>
+struct __with_default
+{
+ template <class... _Args>
+ using __f =
+ __minvoke<__if_c<__minvocable<_Fn, _Args...>, _Fn, __mconst<_Default>>,
+ _Args...>;
+};
+
+template <class _Fn, class _Continuation = __q<__types>>
+struct __transform
+{
+ template <class... _Args>
+ using __f = __minvoke<_Continuation, __minvoke<_Fn, _Args>...>;
+};
+
+template <bool>
+struct __mfold_right_
+{
+ template <class _Fn, class _State, class _Head, class... _Tail>
+ using __f = __minvoke<__mfold_right_<sizeof...(_Tail) == 0>, _Fn,
+ __minvoke<_Fn, _State, _Head>, _Tail...>;
+};
+template <>
+struct __mfold_right_<true>
+{ // empty pack
+ template <class _Fn, class _State, class...>
+ using __f = _State;
+};
+
+template <class _Init, class _Fn>
+struct __mfold_right
+{
+ template <class... _Args>
+ using __f =
+ __minvoke<__mfold_right_<sizeof...(_Args) == 0>, _Fn, _Init, _Args...>;
+};
+
+template <class _Continuation, class...>
+struct __mconcat_
+{};
+template <class _Continuation, class... _As>
+ requires(sizeof...(_As) == 0) && __minvocable<_Continuation, _As...>
+struct __mconcat_<_Continuation, _As...>
+{
+ using __t = __minvoke<_Continuation, _As...>;
+};
+template <class _Continuation, template <class...> class _A, class... _As>
+ requires __minvocable<_Continuation, _As...>
+struct __mconcat_<_Continuation, _A<_As...>>
+{
+ using __t = __minvoke<_Continuation, _As...>;
+};
+template <class _Continuation, template <class...> class _A, class... _As,
+ template <class...> class _B, class... _Bs>
+ requires __minvocable<_Continuation, _As..., _Bs...>
+struct __mconcat_<_Continuation, _A<_As...>, _B<_Bs...>>
+{
+ using __t = __minvoke<_Continuation, _As..., _Bs...>;
+};
+template <class _Continuation, template <class...> class _A, class... _As,
+ template <class...> class _B, class... _Bs,
+ template <class...> class _C, class... _Cs>
+ requires __minvocable<_Continuation, _As..., _Bs..., _Cs...>
+struct __mconcat_<_Continuation, _A<_As...>, _B<_Bs...>, _C<_Cs...>>
+{
+ using __t = __minvoke<_Continuation, _As..., _Bs..., _Cs...>;
+};
+template <class _Continuation, template <class...> class _A, class... _As,
+ template <class...> class _B, class... _Bs,
+ template <class...> class _C, class... _Cs,
+ template <class...> class _D, class... _Ds, class... _Tail>
+struct __mconcat_<_Continuation, _A<_As...>, _B<_Bs...>, _C<_Cs...>, _D<_Ds...>,
+ _Tail...> :
+ __mconcat_<_Continuation, __types<_As..., _Bs..., _Cs..., _Ds...>, _Tail...>
+{};
+
+template <class _Continuation = __q<__types>>
+struct __mconcat
+{
+ template <class... _Args>
+ using __f = __t<__mconcat_<_Continuation, _Args...>>;
+};
template <class _Fn>
struct __curry
@@ -424,19 +315,24 @@
template <class _Fn, class _List>
using __mapply = __minvoke<__uncurry<_Fn>, _List>;
+struct __msize
+{
+ template <class... _Ts>
+ using __f = __msize_t<sizeof...(_Ts)>;
+};
+
+template <class _Ty>
struct __mcount
{
template <class... _Ts>
- using __f = std::integral_constant<std::size_t, sizeof...(_Ts)>;
+ using __f = __msize_t<(__v<std::is_same<_Ts, _Ty>> + ... + 0)>;
};
template <class _Fn>
struct __mcount_if
{
template <class... _Ts>
- using __f =
- std::integral_constant<std::size_t,
- (bool(__minvoke1<_Fn, _Ts>::value) + ...)>;
+ using __f = __msize_t<(bool(__v<__minvoke<_Fn, _Ts>>) + ... + 0)>;
};
template <class _T>
@@ -468,7 +364,7 @@
template <class... _Ts>
using __f = __mapply<
_Continuation,
- __minvoke<__fold_right<__types<>, __push_back_unique<>>, _Ts...>>;
+ __minvoke<__mfold_right<__types<>, __push_back_unique<>>, _Ts...>>;
};
template <class...>
@@ -483,7 +379,7 @@
struct __mcompose<_Second, _First>
{
template <class... _Args>
- using __f = __minvoke1<_Second, __minvoke<_First, _Args...>>;
+ using __f = __minvoke<_Second, __minvoke<_First, _Args...>>;
};
template <class _Last, class _Penultimate, class... _Rest>
@@ -491,8 +387,8 @@
{
template <class... _Args>
using __f =
- __minvoke1<_Last,
- __minvoke<__mcompose<_Penultimate, _Rest...>, _Args...>>;
+ __minvoke<_Last,
+ __minvoke<__mcompose<_Penultimate, _Rest...>, _Args...>>;
};
template <class _Old, class _New, class _Continuation = __q<__types>>
@@ -508,8 +404,8 @@
{
template <class... _Args>
using __f =
- __minvoke<__concat<_Continuation>, __if<std::is_same<_Args, _Old>,
- __types<>, __types<_Args>>...>;
+ __minvoke<__mconcat<_Continuation>, __if<std::is_same<_Args, _Old>,
+ __types<>, __types<_Args>>...>;
};
template <class _Return>
@@ -519,42 +415,112 @@
using __f = _Return(_Args...);
};
+// A very simple std::declval replacement that doesn't handle void
template <class _T>
-_T&& __declval() noexcept
- requires true;
-
-template <class>
-void __declval() noexcept;
+_T&& __declval() noexcept;
// For copying cvref from one type to another:
-template <class _Member, class _Self>
-_Member _Self::*__memptr(const _Self&);
-
-template <typename _Self, typename _Member>
-using __member_t =
- decltype((__declval<_Self>().*__memptr<_Member>(__declval<_Self>())));
-
-template <class... _As>
-struct __front_;
-template <class _A, class... _As>
-struct __front_<_A, _As...>
+struct __cp
{
- using __t = _A;
+ template <class _T>
+ using __f = _T;
};
+struct __cpc
+{
+ template <class _T>
+ using __f = const _T;
+};
+struct __cplr
+{
+ template <class _T>
+ using __f = _T&;
+};
+struct __cprr
+{
+ template <class _T>
+ using __f = _T&&;
+};
+struct __cpclr
+{
+ template <class _T>
+ using __f = const _T&;
+};
+struct __cpcrr
+{
+ template <class _T>
+ using __f = const _T&&;
+};
+
+template <class>
+extern __cp __cpcvr;
+template <class _T>
+extern __cpc __cpcvr<const _T>;
+template <class _T>
+extern __cplr __cpcvr<_T&>;
+template <class _T>
+extern __cprr __cpcvr<_T&&>;
+template <class _T>
+extern __cpclr __cpcvr<const _T&>;
+template <class _T>
+extern __cpcrr __cpcvr<const _T&&>;
+template <class _T>
+using __copy_cvref_fn = decltype(__cpcvr<_T>);
+
+template <class _From, class _To>
+using __copy_cvref_t = __minvoke<__copy_cvref_fn<_From>, _To>;
+
+template <class _Ty, class...>
+using __mfront_ = _Ty;
template <class... _As>
- requires(sizeof...(_As) != 0)
-using __front = __t<__front_<_As...>>;
+using __mfront = __meval<__mfront_, _As...>;
template <class... _As>
requires(sizeof...(_As) == 1)
-using __single = __front<_As...>;
+using __msingle = __mfront<_As...>;
template <class _Ty>
-struct __single_or
+using __msingle_or = __mbind_back_q<__mfront_, _Ty>;
+
+template <class _Continuation = __q<__types>>
+struct __pop_front
{
- template <class... _As>
- requires(sizeof...(_As) <= 1)
- using __f = __front<_As..., _Ty>;
+ template <class, class... _Ts>
+ using __f = __minvoke<_Continuation, _Ts...>;
};
+// For hiding a template type parameter from ADL
+template <class _Ty>
+struct _X
+{
+ using __t = struct _T
+ {
+ using __t = _Ty;
+ };
+};
+template <class _Ty>
+using __x = __t<_X<_Ty>>;
+
+template <class _Ty>
+struct _Y
+{
+ using __t = _Ty;
+};
+
+template <class _Ty>
+concept __has_id = requires { typename _Ty::__id; };
+template <bool = true>
+struct __id_
+{
+ template <class _Ty>
+ using __f = typename _Ty::__id;
+};
+template <>
+struct __id_<false>
+{
+ template <class _Ty>
+ using __f = _Y<_Ty>;
+};
+template <class _Ty>
+using __id = __minvoke<__id_<__has_id<_Ty>>, _Ty>;
+
template <class _Fun, class... _As>
concept __callable = requires(_Fun&& __fun, _As&&... __as) {
((_Fun &&) __fun)((_As &&) __as...);
@@ -566,8 +532,19 @@
((_Fun &&) __fun)((_As &&) __as...)
} noexcept;
};
+
+#if STDEXEC_NVHPC()
+// nvc++ doesn't cache the results of alias template specializations.
+// To avoid repeated computation of the same function return type,
+// cache the result ourselves in a class template specialization.
+template <class _Fun, class... _As>
+using __call_result_ = decltype(__declval<_Fun>()(__declval<_As>()...));
+template <class _Fun, class... _As>
+using __call_result_t = __t<__mdefer<__q<__call_result_>, _Fun, _As...>>;
+#else
template <class _Fun, class... _As>
using __call_result_t = decltype(__declval<_Fun>()(__declval<_As>()...));
+#endif
// For working around clang's lack of support for CWG#2369:
// http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#2369
@@ -607,12 +584,11 @@
template <class _Fn, class _Continuation, template <class...> class _C,
class... _Cs, template <class...> class _D, class... _Ds>
requires requires {
- typename __minvoke<_Continuation,
- __minvoke2<_Fn, _Cs, _Ds>...>;
+ typename __minvoke<_Continuation, __minvoke<_Fn, _Cs, _Ds>...>;
}
struct __mzip_with2_<_Fn, _Continuation, _C<_Cs...>, _D<_Ds...>>
{
- using __t = __minvoke<_Continuation, __minvoke2<_Fn, _Cs, _Ds>...>;
+ using __t = __minvoke<_Continuation, __minvoke<_Fn, _Cs, _Ds>...>;
};
template <class _Fn, class _Continuation = __q<__types>>
@@ -622,142 +598,264 @@
using __f = __t<__mzip_with2_<_Fn, _Continuation, _C, _D>>;
};
+#if STDEXEC_GCC() && (__GNUC__ < 12)
+template <class>
+extern int __mconvert_indices;
template <std::size_t... _Indices>
-auto __mconvert_indices(std::index_sequence<_Indices...>)
- -> __types<__index<_Indices>...>;
+extern __types<__msize_t<_Indices>...>
+ __mconvert_indices<std::index_sequence<_Indices...>>;
template <std::size_t _N>
using __mmake_index_sequence =
- decltype(__mconvert_indices(std::make_index_sequence<_N>{}));
+ decltype(stdexec::__mconvert_indices<std::make_index_sequence<_N>>);
+#else
+template <std::size_t... _Indices>
+__types<__msize_t<_Indices>...>
+ __mconvert_indices(std::index_sequence<_Indices...>*);
+template <std::size_t _N>
+using __mmake_index_sequence = decltype(stdexec::__mconvert_indices(
+ (std::make_index_sequence<_N>*)nullptr));
+#endif
+
template <class... _Ts>
using __mindex_sequence_for = __mmake_index_sequence<sizeof...(_Ts)>;
-template <class _Fn, class _Continuation, class... _Args>
+template <bool>
struct __mfind_if_
{
- using __t = __minvoke<_Continuation, _Args...>;
+ template <class _Fn, class _Continuation, class _Head, class... _Tail>
+ using __f = __minvoke<
+ __if_c<__v<__minvoke<_Fn, _Head>>, __mbind_front<_Continuation, _Head>,
+ __mbind_front<__mfind_if_<(sizeof...(_Tail) != 0)>, _Fn,
+ _Continuation>>,
+ _Tail...>;
};
-template <class _Fn, class _Continuation, class _Head, class... _Tail>
-struct __mfind_if_<_Fn, _Continuation, _Head, _Tail...> :
- __mfind_if_<_Fn, _Continuation, _Tail...>
-{};
-template <class _Fn, class _Continuation, class _Head, class... _Tail>
- requires __v<__minvoke1<_Fn, _Head>>
-struct __mfind_if_<_Fn, _Continuation, _Head, _Tail...>
+template <>
+struct __mfind_if_<false>
{
- using __t = __minvoke<_Continuation, _Head, _Tail...>;
+ template <class _Fn, class _Continuation>
+ using __f = __minvoke<_Continuation>;
};
+
template <class _Fn, class _Continuation = __q<__types>>
struct __mfind_if
{
template <class... _Args>
- using __f = __t<__mfind_if_<_Fn, _Continuation, _Args...>>;
+ using __f = __minvoke<__mfind_if_<(sizeof...(_Args) != 0)>, _Fn,
+ _Continuation, _Args...>;
};
template <class _Fn>
struct __mfind_if_i
{
template <class... _Args>
- using __f = __index<(sizeof...(_Args) -
- __v<__minvoke<__mfind_if<_Fn, __mcount>, _Args...>>)>;
+ using __f = __msize_t<(sizeof...(_Args) -
+ __v<__minvoke<__mfind_if<_Fn, __msize>, _Args...>>)>;
};
-template <class... _Bools>
-using __mand = __bool<(__v<_Bools> && ...)>;
-template <class... _Bools>
-using __mor = __bool<(__v<_Bools> || ...)>;
-template <class _Bool>
-using __mnot = __bool<!__v<_Bool>>;
+template <class... _Booleans>
+using __mand = __bool<(__v<_Booleans> && ...)>;
+template <class... _Booleans>
+using __mor = __bool<(__v<_Booleans> || ...)>;
+template <class _Boolean>
+using __mnot = __bool<!__v<_Boolean>>;
template <class _Fn>
struct __mall_of
{
template <class... _Args>
- using __f = __mand<__minvoke1<_Fn, _Args>...>;
+ using __f = __mand<__minvoke<_Fn, _Args>...>;
};
template <class _Fn>
struct __mnone_of
{
template <class... _Args>
- using __f = __mand<__mnot<__minvoke1<_Fn, _Args>>...>;
+ using __f = __mand<__mnot<__minvoke<_Fn, _Args>>...>;
};
template <class _Fn>
struct __many_of
{
template <class... _Args>
- using __f = __mor<__minvoke1<_Fn, _Args>...>;
+ using __f = __mor<__minvoke<_Fn, _Args>...>;
};
-template <class _Ty>
-struct __mtypeof__
-{
- using __t = _Ty;
-};
-template <class _Ty>
-using __mtypeof__t = __t<__mtypeof__<_Ty>>;
-template <class _Ret, class... _Args>
- requires __callable<_Ret, __mtypeof__t<_Args>...>
-struct __mtypeof__<_Ret (*)(_Args...)>
-{
- using __t = __call_result_t<_Ret, __mtypeof__t<_Args>...>;
-};
-template <class _Ty>
-struct __mtypeof_
-{};
-template <class _Ret, class... _Args>
- requires __callable<_Ret, __mtypeof__t<_Args>...>
-struct __mtypeof_<_Ret(_Args...)>
-{
- using __t = __call_result_t<_Ret, __mtypeof__t<_Args>...>;
-};
-template <class _Ty>
-using __mtypeof = __t<__mtypeof_<_Ty>>;
+#if __has_builtin(__type_pack_element)
+template <std::size_t _N, class... _Ts>
+using __m_at = __type_pack_element<_N, _Ts...>;
+#else
+template <std::size_t>
+using __void_ptr = void*;
template <class _Ty>
-using __mrequires = __bool<__valid1<__mtypeof, _Ty>>;
-template <class _Ty>
-concept __mrequires_v = __valid1<__mtypeof, _Ty>;
+using __mtype_ptr = __mtype<_Ty>*;
template <class _Ty>
-inline constexpr bool __mnoexcept__ = true;
-template <class _Ret, class... _Args>
- requires __callable<_Ret, __mtypeof__t<_Args>...>
-inline constexpr bool __mnoexcept__<_Ret (*)(_Args...)> =
- (__mnoexcept__<_Args> && ...) &&
- __nothrow_callable<_Ret, __mtypeof__t<_Args>...>;
-template <class _Ty>
-inline constexpr bool __mnoexcept_v = false;
-template <class _Ret, class... _Args>
- requires __callable<_Ret, __mtypeof__t<_Args>...>
-inline constexpr bool __mnoexcept_v<_Ret(_Args...)> =
- (__mnoexcept__<_Args> && ...) &&
- __nothrow_callable<_Ret, __mtypeof__t<_Args>...>;
-template <class _Ty>
-using __mnoexcept = __bool<__mnoexcept_v<_Ty>>;
+struct __m_at_;
-template <class... _Sigs>
-struct __msignatures
+template <std::size_t... _Is>
+struct __m_at_<std::index_sequence<_Is...>>
{
- template <class _Continuation, class... _Extra>
- using __f = __minvoke<_Continuation, _Sigs..., _Extra...>;
+ template <class _U, class... _Us>
+ static _U __f_(__void_ptr<_Is>..., _U*, _Us*...);
+ template <class... _Ts>
+ using __f = __t<decltype(__m_at_::__f_(__mtype_ptr<_Ts>()...))>;
};
-template <class _Signatures>
-using __many_well_formed =
- __minvoke1<_Signatures, __many_of<__q1<__mrequires>>>;
-template <class _Signatures, class... _Extra>
-using __mwhich_t =
- __minvoke<_Signatures, __mfind_if<__q1<__mrequires>, __q<__front>>,
- _Extra...>;
-template <class _Signatures, class... _Extra>
-using __mwhich_i =
- __index<(__v<__minvoke<_Signatures, __mcount, _Extra...>> -
- __v<__minvoke<_Signatures, __mfind_if<__q1<__mrequires>, __mcount>,
- _Extra...>>)>;
-template <class _Ty, bool _Noexcept = true>
+
+template <std::size_t _N, class... _Ts>
+using __m_at = __minvoke<__m_at_<std::make_index_sequence<_N>>, _Ts...>;
+#endif
+
+template <std::size_t _N>
+struct __placeholder_;
+template <std::size_t _N>
+using __placeholder = __placeholder_<_N>*;
+
+using __0 = __placeholder<0>;
+using __1 = __placeholder<1>;
+using __2 = __placeholder<2>;
+using __3 = __placeholder<3>;
+
+template <class _Ty, class _Noexcept = __bool<true>>
struct __mconstruct
{
template <class... _As>
auto operator()(_As&&... __as) const
- noexcept(_Noexcept&& noexcept(_Ty((_As &&) __as...)))
- -> decltype(_Ty((_As &&) __as...));
+ noexcept(__v<_Noexcept>&& noexcept(_Ty((_As &&) __as...)))
+ -> decltype(_Ty((_As &&) __as...))
+ {
+ return _Ty((_As &&) __as...);
+ }
};
+
+template <template <class...> class _C, class _Noexcept = __bool<true>>
+using __mconstructor_for = __mcompose<__q<__mconstruct>, __q<_C>>;
+
+template <std::size_t>
+using __ignore_t = __ignore;
+
+template <std::size_t... _Is, class _Ty, class... _Us>
+_Ty&& __nth_pack_element_(__ignore_t<_Is>..., _Ty&& __t, _Us&&...) noexcept
+{
+ return (_Ty &&) __t;
+}
+template <std::size_t _N, class... _Ts>
+constexpr decltype(auto) __nth_pack_element(_Ts&&... __ts) noexcept
+{
+ return [&]<std::size_t... _Is>(std::index_sequence<_Is...>*) noexcept
+ -> decltype(auto)
+ {
+ return stdexec::__nth_pack_element_<_Is...>((_Ts &&) __ts...);
+ }
+ ((std::make_index_sequence<_N>*)nullptr);
+}
+
+template <class _Ty>
+struct __mdispatch_
+{
+ template <class... _Ts>
+ _Ty operator()(_Ts&&...) const noexcept(noexcept(_Ty{}))
+ {
+ return _Ty{};
+ }
+};
+template <std::size_t _N>
+struct __mdispatch_<__placeholder<_N>>
+{
+ template <class... _Ts>
+ decltype(auto) operator()(_Ts&&... __ts) const noexcept
+ {
+ return stdexec::__nth_pack_element<_N>((_Ts &&) __ts...);
+ }
+};
+template <std::size_t _N>
+struct __mdispatch_<__placeholder<_N>&>
+{
+ template <class... _Ts>
+ decltype(auto) operator()(_Ts&&... __ts) const noexcept
+ {
+ return stdexec::__nth_pack_element<_N>(__ts...);
+ }
+};
+template <std::size_t _N>
+struct __mdispatch_<__placeholder<_N>&&>
+{
+ template <class... _Ts>
+ decltype(auto) operator()(_Ts&&... __ts) const noexcept
+ {
+ return std::move(stdexec::__nth_pack_element<_N>(__ts...));
+ }
+};
+template <std::size_t _N>
+struct __mdispatch_<const __placeholder<_N>&>
+{
+ template <class... _Ts>
+ decltype(auto) operator()(_Ts&&... __ts) const noexcept
+ {
+ return std::as_const(stdexec::__nth_pack_element<_N>(__ts...));
+ }
+};
+template <class _Ret, class... _Args>
+struct __mdispatch_<_Ret (*)(_Args...)>
+{
+ template <class... _Ts>
+ requires(__callable<__mdispatch_<_Args>, _Ts...> && ...) &&
+ __callable<_Ret,
+ __call_result_t<__mdispatch_<_Args>, _Ts...>...>
+ auto operator()(_Ts&&... __ts) const
+ noexcept(__nothrow_callable<
+ _Ret, __call_result_t<__mdispatch_<_Args>, _Ts...>...>)
+ -> __call_result_t<
+ _Ret, __call_result_t<__mdispatch_<_Args>, _Ts...>...>
+ {
+ return _Ret{}(__mdispatch_<_Args>{}((_Ts &&) __ts...)...);
+ }
+};
+
+template <class _Ty>
+struct __mdispatch
+{};
+template <class _Ret, class... _Args>
+struct __mdispatch<_Ret(_Args...)>
+{
+ template <class... _Ts>
+ requires(__callable<__mdispatch_<_Args>, _Ts...> && ...) &&
+ __callable<_Ret,
+ __call_result_t<__mdispatch_<_Args>, _Ts...>...>
+ auto operator()(_Ts&&... __ts) const
+ noexcept(__nothrow_callable<
+ _Ret, __call_result_t<__mdispatch_<_Args>, _Ts...>...>)
+ -> __call_result_t<
+ _Ret, __call_result_t<__mdispatch_<_Args>, _Ts...>...>
+ {
+ return _Ret{}(__mdispatch_<_Args>{}((_Ts &&) __ts...)...);
+ }
+};
+template <class _Ty, class... _Ts>
+concept __dispatchable = __callable<__mdispatch<_Ty>, _Ts...>;
+
+template <class _Ty, class... _Ts>
+concept __nothrow_dispatchable = __nothrow_callable<__mdispatch<_Ty>, _Ts...>;
+
+template <class _Ty, class... _Ts>
+using __dispatch_result_t = __call_result_t<__mdispatch<_Ty>, _Ts...>;
+
+template <class _Signature, class... _Args>
+using __try_dispatch_ = __bool<__dispatchable<_Signature, _Args...>>;
+template <class _Signatures, class _Continuation = __q<__mfront>>
+struct __which
+{};
+template <template <class...> class _C, class... _Signatures,
+ class _Continuation>
+struct __which<_C<_Signatures...>, _Continuation>
+{
+ template <class... _Args>
+ using __f = __minvoke<
+ __mfind_if<__mbind_back_q<__try_dispatch_, _Args...>, _Continuation>,
+ _Signatures...>;
+};
+
+template <class _Signatures, class _DefaultFn, class... _Args>
+using __make_dispatcher = __minvoke<
+ __if_c<__minvocable<__which<_Signatures>, _Args...>,
+ __mcompose<__q<__mdispatch>, __which<_Signatures>>, _DefaultFn>,
+ _Args...>;
} // namespace stdexec
diff --git a/include/sdbusplus/async/stdexec/commit.info b/include/sdbusplus/async/stdexec/commit.info
index e75984e..9fe5b5f 100644
--- a/include/sdbusplus/async/stdexec/commit.info
+++ b/include/sdbusplus/async/stdexec/commit.info
@@ -1 +1 @@
-c3d8aa9ed3a059f6575cbf0b9684ed0b4a6429de
+218931e835b0313c67be469adb721df8c43eb684
diff --git a/include/sdbusplus/async/stdexec/concepts.hpp b/include/sdbusplus/async/stdexec/concepts.hpp
index f2ef2c2..d95c44c 100644
--- a/include/sdbusplus/async/stdexec/concepts.hpp
+++ b/include/sdbusplus/async/stdexec/concepts.hpp
@@ -22,42 +22,46 @@
#include <version>
// Perhaps the stdlib lacks support for concepts though:
-#if __has_include(<concepts>) && __cpp_lib_concepts >= 202002
+#if __has_include(<concepts>) && __cpp_lib_concepts >= 202002
+#define STDEXEC_HAS_STD_CONCEPTS_HEADER() 1
+#else
+#define STDEXEC_HAS_STD_CONCEPTS_HEADER() 0
+#endif
+
+#if STDEXEC_HAS_STD_CONCEPTS_HEADER()
#include <concepts>
-namespace __std_concepts_polyfill
-{
-using std::constructible_from;
-using std::convertible_to;
-using std::copy_constructible;
-using std::derived_from;
-using std::destructible;
-using std::equality_comparable;
-using std::integral;
-using std::move_constructible;
-using std::same_as;
-} // namespace __std_concepts_polyfill
#else
#include <type_traits>
+#endif
-namespace __std_concepts_polyfill
+namespace stdexec::__std_concepts
{
-// C++20 concepts
#if defined(__clang__)
template <class _A, class _B>
-concept same_as = __is_same(_A, _B) && __is_same(_B, _A);
+concept __same_as = __is_same(_A, _B);
#elif defined(__GNUC__)
template <class _A, class _B>
-concept same_as = __is_same_as(_A, _B) && __is_same_as(_B, _A);
+concept __same_as = __is_same_as(_A, _B);
#else
template <class _A, class _B>
-inline constexpr bool __same_as_v = false;
+inline constexpr bool __same_as = false;
template <class _A>
-inline constexpr bool __same_as_v<_A, _A> = true;
-
-template <class _A, class _B>
-concept same_as = __same_as_v<_A, _B> && __same_as_v<_B, _A>;
+inline constexpr bool __same_as<_A, _A> = true;
#endif
+// Make sure we're using a same_as concept that doesn't instantiate std::is_same
+template <class _A, class _B>
+concept same_as = __same_as<_A, _B> && __same_as<_B, _A>;
+
+#if STDEXEC_HAS_STD_CONCEPTS_HEADER()
+
+using std::convertible_to;
+using std::derived_from;
+using std::equality_comparable;
+using std::integral;
+
+#else
+
template <class T>
concept integral = std::is_integral_v<T>;
@@ -80,9 +84,69 @@
__t != __t
} -> convertible_to<bool>;
};
+#endif
+} // namespace stdexec::__std_concepts
+namespace stdexec
+{
+using namespace __std_concepts;
+using std::decay_t;
+
+// // TODO: this makes nvc++ sad. Find out why.
+// template <class _Ty>
+// _Ty __decay__(const _Ty&);
+// template <class _Ty>
+// _Ty* __decay__(_Ty*);
+
+// template <class _Ty>
+// auto __decay_(_Ty&&(*__fn)()) -> decltype((__decay__)(__fn()));
+// template <class>
+// void __decay_(...);
+
+// template <class _Ty>
+// using decay_t = decltype((__decay_<_Ty>)(0));
+
+// C++20 concepts
+template <class _T, class _U>
+concept __decays_to = __same_as<decay_t<_T>, _U>;
+
+template <class...>
+concept __true = true;
+
+template <class _C>
+concept __class = __true<int _C::*> && (!__same_as<const _C, _C>);
+
+template <class _T, class... _As>
+concept __one_of = (__same_as<_T, _As> || ...);
+
+template <class _T, class... _Us>
+concept __all_of = (__same_as<_T, _Us> && ...);
+
+template <class _T, class... _Us>
+concept __none_of = ((!__same_as<_T, _Us>) && ...);
+
+// Not exactly right, but close.
template <class _T>
-concept destructible = std::is_nothrow_destructible_v<_T>;
+concept __boolean_testable_ = convertible_to<_T, bool>;
+
+// Avoid using libstdc++'s object concepts because they instantiate a
+// lot of templates.
+template <class _Ty>
+inline constexpr bool __destructible_ =
+ requires {
+ {
+ ((_Ty && (*)() noexcept) nullptr)().~_Ty()
+ } noexcept;
+ };
+template <class _Ty>
+inline constexpr bool __destructible_<_Ty&> = true;
+template <class _Ty>
+inline constexpr bool __destructible_<_Ty&&> = true;
+template <class _Ty, std::size_t _N>
+inline constexpr bool __destructible_<_Ty[_N]> = __destructible_<_Ty>;
+
+template <class T>
+concept destructible = __destructible_<T>;
#if __has_builtin(__is_constructible)
template <class _T, class... _As>
@@ -98,37 +162,6 @@
template <class _T>
concept copy_constructible = move_constructible<_T> &&
constructible_from<_T, _T const&>;
-} // namespace __std_concepts_polyfill
-
-namespace std
-{
-using namespace __std_concepts_polyfill;
-}
-#endif
-
-namespace stdexec
-{
-using namespace __std_concepts_polyfill;
-using std::decay_t;
-
-template <class _T, class _U>
-concept __decays_to = same_as<decay_t<_T>, _U>;
-
-template <class _C>
-concept __class = std::is_class_v<_C> && __decays_to<_C, _C>;
-
-template <class _T, class... _As>
-concept __one_of = (same_as<_T, _As> || ...);
-
-template <class _T, class... _Us>
-concept __all_of = (same_as<_T, _Us> && ...);
-
-template <class _T, class... _Us>
-concept __none_of = ((!same_as<_T, _Us>) && ...);
-
-// Not exactly right, but close.
-template <class _T>
-concept __boolean_testable_ = convertible_to<_T, bool>;
template <class _T>
concept __movable_value = move_constructible<decay_t<_T>> &&
@@ -164,3 +197,10 @@
concept __nothrow_decay_copyable =
__nothrow_constructible_from<decay_t<_Ty>, _Ty>;
} // namespace stdexec
+
+#if !STDEXEC_HAS_STD_CONCEPTS_HEADER()
+namespace std
+{
+using namespace stdexec::__std_concepts;
+}
+#endif
diff --git a/include/sdbusplus/async/stdexec/execution.hpp b/include/sdbusplus/async/stdexec/execution.hpp
index c44d60c..10f6abe 100644
--- a/include/sdbusplus/async/stdexec/execution.hpp
+++ b/include/sdbusplus/async/stdexec/execution.hpp
@@ -35,14 +35,15 @@
#include <variant>
#if STDEXEC_CLANG()
-#define _STRINGIZE(__arg) #__arg
-#define _PRAGMA_PUSH() _Pragma("GCC diagnostic push")
-#define _PRAGMA_POP() _Pragma("GCC diagnostic pop")
-#define _PRAGMA_IGNORE(__arg) _Pragma(_STRINGIZE(GCC diagnostic ignored __arg))
+#define STDEXEC_STRINGIZE(__arg) #__arg
+#define STDEXEC_PRAGMA_PUSH() _Pragma("GCC diagnostic push")
+#define STDEXEC_PRAGMA_POP() _Pragma("GCC diagnostic pop")
+#define STDEXEC_PRAGMA_IGNORE(__arg) \
+ _Pragma(STDEXEC_STRINGIZE(GCC diagnostic ignored __arg))
#else
-#define _PRAGMA_PUSH()
-#define _PRAGMA_POP()
-#define _PRAGMA_IGNORE(__arg)
+#define STDEXEC_PRAGMA_PUSH()
+#define STDEXEC_PRAGMA_POP()
+#define STDEXEC_PRAGMA_IGNORE(__arg)
#endif
#if STDEXEC_NVHPC() || STDEXEC_GCC()
@@ -55,9 +56,9 @@
#pragma diag_suppress 497
#endif
-_PRAGMA_PUSH()
-_PRAGMA_IGNORE("-Wundefined-inline")
-_PRAGMA_IGNORE("-Wundefined-internal")
+STDEXEC_PRAGMA_PUSH()
+STDEXEC_PRAGMA_IGNORE("-Wundefined-inline")
+STDEXEC_PRAGMA_IGNORE("-Wundefined-internal")
namespace stdexec
{
@@ -115,109 +116,126 @@
namespace __env
{
struct __empty_env
-{};
+{
+ using __t = __empty_env;
+ using __id = __empty_env;
+};
struct no_env
{
+ using __t = no_env;
+ using __id = no_env;
template <class _Tag, same_as<no_env> _Self, class... _Ts>
friend void tag_invoke(_Tag, _Self, _Ts&&...) = delete;
};
-template <__class _Tag, class _Value>
+template <__class _Tag, class _Value = __none_such>
requires copy_constructible<std::unwrap_reference_t<_Value>>
-struct __with_x
+struct __with
{
+ using __tag_t = _Tag;
+ using __value_t = _Value;
+ _Value __value_;
struct __t
{
- using __tag_t = _Tag;
- using __value_t = _Value;
- [[no_unique_address]] std::unwrap_reference_t<_Value> __value_;
+ using __id = __with;
+ using __val_or_ref_t = std::unwrap_reference_t<_Value>;
+
+ [[no_unique_address]] __val_or_ref_t __value_;
+
+ __t(__with&& __w) : __value_(((__with &&) __w).__value_) {}
template <same_as<_Tag> _T, class... _Ts>
- friend auto tag_invoke(_T, const __t& __self, _Ts&&...) noexcept(
- std::is_nothrow_copy_constructible_v<
- std::unwrap_reference_t<_Value>>)
- -> std::unwrap_reference_t<_Value>
+ friend __val_or_ref_t
+ tag_invoke(_T, const __t& __self, _Ts&&...) noexcept(
+ std::is_nothrow_copy_constructible_v<__val_or_ref_t>)
{
return __self.__value_;
}
};
};
template <class _Tag>
-struct __with_x<_Tag, __none_such>
+struct __with<_Tag, __none_such>
{
+ using __tag_t = _Tag;
+ using __value_t = __none_such;
struct __t
{
- using __tag_t = _Tag;
- using __value_t = __none_such;
+ using __id = __with;
+ __t(__with) {}
template <same_as<_Tag> _T, class... _Ts>
friend void tag_invoke(_T, const __t&, _Ts&&...) = delete;
};
};
-template <class _With>
-struct __with_ : _With
-{};
-template <class _Tag, class _Value = __none_such>
-using __with_t = __with_<__t<__with_x<_Tag, decay_t<_Value>>>>;
template <__class _Tag, class _Value>
-__with_t<_Tag, _Value> __with(_Tag, _Value&& __val)
+__with<_Tag, decay_t<_Value>> __with_(_Tag, _Value&& __val)
{
- return {{(_Value &&) __val}};
+ return {(_Value &&) __val};
}
template <__class _Tag>
-__with_t<_Tag, __none_such> __with(_Tag)
+__with<_Tag> __with_(_Tag)
{
- return {{}};
+ return {};
}
-template <class _BaseEnvId, class... _Withs>
-struct __env_ : _Withs...
+template <class _BaseEnvId, class... _WithIds>
+struct __env
{
using _BaseEnv = stdexec::__t<_BaseEnvId>;
- using __base_env_t = _BaseEnv;
- [[no_unique_address]] _BaseEnv __base_env_{};
+ template <class _WithId>
+ using __tag_of = typename _WithId::__tag_t;
+ template <class _Self>
+ using __base_env_of = __make_dependent_on<_BaseEnv, _Self>;
- // Forward the receiver queries:
- template <
- __none_of<typename _Withs::__tag_t..., get_completion_signatures_t>
- _Tag,
- same_as<__env_> _Self, class... _As>
- requires __callable<_Tag, const typename _Self::__base_env_t&, _As...>
- friend auto tag_invoke(_Tag __tag, const _Self& __self,
- _As&&... __as) noexcept
- -> __call_result_if_t<same_as<_Self, __env_>, _Tag,
- const typename _Self::__base_env_t&, _As...>
+ struct __t : stdexec::__t<_WithIds>...
{
- return ((_Tag &&) __tag)(__self.__base_env_, (_As &&) __as...);
- }
+ using __id = __env;
+ [[no_unique_address]] _BaseEnv __base_env_{};
+
+ // Forward the receiver queries:
+ template <
+ __none_of<__tag_of<_WithIds>..., get_completion_signatures_t> _Tag,
+ same_as<__t> _Self, class... _As>
+ requires __callable<_Tag, const __base_env_of<_Self>&, _As...>
+ friend auto tag_invoke(_Tag __tag, const _Self& __self,
+ _As&&... __as) noexcept
+ -> __call_result_if_t<same_as<_Self, __t>, _Tag,
+ const __base_env_of<_Self>&, _As...>
+ {
+ return ((_Tag &&) __tag)(__self.__base_env_, (_As &&) __as...);
+ }
+ };
};
-template <class _BaseEnv, class... _Withs>
-using __env = __env_<__x<_BaseEnv>, _Withs...>;
+template <class _BaseEnv, class... _WithIds>
+using __env_t = __t<__env<stdexec::__id<_BaseEnv>, _WithIds...>>;
// For making an evaluation environment from key/value pairs and optionally
// another environment.
struct __make_env_t
{
- template <class _W, class... _Ws>
- auto operator()(__with_<_W> __w, __with_<_Ws>... __ws) const
- noexcept(std::is_nothrow_move_constructible_v<_W> &&
- (std::is_nothrow_move_constructible_v<_Ws> && ...))
- -> __env<__empty_env, _W, _Ws...>
+ template <class _Tag, class _Value, class... _Tags, class... _Values>
+ auto operator()(__with<_Tag, _Value> __w,
+ __with<_Tags, _Values>... __ws) const
+ noexcept(std::is_nothrow_move_constructible_v<_Value> &&
+ (std::is_nothrow_move_constructible_v<_Values> && ...))
+ -> __env_t<__empty_env, __with<_Tag, _Value>,
+ __with<_Tags, _Values>...>
{
- return {std::move(__w), std::move(__ws)..., {}};
+ return {{std::move(__w)}, {std::move(__ws)}..., {}};
}
- template <__none_of<no_env> _BaseEnv, class... _Ws>
- auto operator()(_BaseEnv&& __base_env, __with_<_Ws>... __ws) const
- -> __env<decay_t<_BaseEnv>, _Ws...>
+ template <__none_of<no_env> _BaseEnv, class... _Tags, class... _Values>
+ requires __is_not_instance_of<_BaseEnv, __with>
+ auto operator()(_BaseEnv&& __base_env, __with<_Tags, _Values>... __ws) const
+ -> __env_t<decay_t<_BaseEnv>, __with<_Tags, _Values>...>
{
- return {std::move(__ws)..., (_BaseEnv &&) __base_env};
+ return {{std::move(__ws)}..., (_BaseEnv &&) __base_env};
}
- template <class... _Ws>
- auto operator()(no_env, __with_<_Ws>...) const noexcept -> no_env
+ template <class... _Tags, class... _Values>
+ no_env operator()(no_env, __with<_Tags, _Values>...) const noexcept
{
return {};
}
@@ -232,15 +250,13 @@
noexcept(nothrow_tag_invocable<get_env_t, const _EnvProvider&>)
-> tag_invoke_result_t<get_env_t, const _EnvProvider&>
{
- using _Env = tag_invoke_result_t<get_env_t, const _EnvProvider&>;
- static_assert(!same_as<_Env, no_env>);
return tag_invoke(*this, __with_env);
}
};
} // namespace __env
using __env::__empty_env;
using __env::__with;
-using __env::__with_t;
+using __env::__with_;
inline constexpr __env::__make_env_t __make_env{};
inline constexpr __env::get_env_t get_env{};
@@ -267,6 +283,9 @@
{
struct set_value_t
{
+ template <class _Fn, class... _Args>
+ using __f = __minvoke<_Fn, _Args...>;
+
template <class _Receiver, class... _As>
requires tag_invocable<set_value_t, _Receiver, _As...>
void operator()(_Receiver&& __rcvr, _As&&... __as) const noexcept
@@ -279,6 +298,10 @@
struct set_error_t
{
+ template <class _Fn, class... _Args>
+ requires(sizeof...(_Args) == 1)
+ using __f = __minvoke<_Fn, _Args...>;
+
template <class _Receiver, class _Error>
requires tag_invocable<set_error_t, _Receiver, _Error>
void operator()(_Receiver&& __rcvr, _Error&& __err) const noexcept
@@ -291,6 +314,10 @@
struct set_stopped_t
{
+ template <class _Fn, class... _Args>
+ requires(sizeof...(_Args) == 0)
+ using __f = __minvoke<_Fn, _Args...>;
+
template <class _Receiver>
requires tag_invocable<set_stopped_t, _Receiver>
void operator()(_Receiver&& __rcvr) const noexcept
@@ -307,6 +334,10 @@
inline constexpr set_error_t set_error{};
inline constexpr set_stopped_t set_stopped{};
+template <class _Tag>
+concept __completion_tag =
+ __one_of<_Tag, set_value_t, set_error_t, set_stopped_t>;
+
inline constexpr struct __try_call_t
{
template <class _Receiver, class _Fun, class... _Args>
@@ -341,8 +372,8 @@
__types<__minvoke<_Ty, _Args...>> __test(set_value_t (*)(_Args...),
set_value_t = {}, _Ty = {});
template <class _Ty = __q<__types>, class _Error>
-__types<__minvoke1<_Ty, _Error>> __test(set_error_t (*)(_Error),
- set_error_t = {}, _Ty = {});
+__types<__minvoke<_Ty, _Error>> __test(set_error_t (*)(_Error),
+ set_error_t = {}, _Ty = {});
template <class _Ty = __q<__types>>
__types<__minvoke<_Ty>> __test(set_stopped_t (*)(), set_stopped_t = {},
_Ty = {});
@@ -362,7 +393,7 @@
template <same_as<set_value_t> _Tag, class _Ty = __q<__types>, class... _Args>
__types<__minvoke<_Ty, _Args...>> __test(_Tag (*)(_Args...));
template <same_as<set_error_t> _Tag, class _Ty = __q<__types>, class _Error>
-__types<__minvoke1<_Ty, _Error>> __test(_Tag (*)(_Error));
+__types<__minvoke<_Ty, _Error>> __test(_Tag (*)(_Error));
template <same_as<set_stopped_t> _Tag, class _Ty = __q<__types>>
__types<__minvoke<_Ty>> __test(_Tag (*)());
template <class, class = void>
@@ -378,10 +409,6 @@
__dependent await_resume();
#endif
};
-} // namespace __compl_sigs
-
-template <same_as<no_env>>
-using dependent_completion_signatures = __compl_sigs::__dependent;
#if STDEXEC_NVHPC()
template <class _Sig>
@@ -399,15 +426,40 @@
using __signal_args_t =
decltype(__compl_sigs::__test<_Tag, _Ty>((_Sig*)nullptr));
#endif
+} // namespace __compl_sigs
+using __compl_sigs::__completion_signature;
-template <__completion_signature... _Sigs>
+template <same_as<no_env>>
+using dependent_completion_signatures = __compl_sigs::__dependent;
+
+template <__compl_sigs::__completion_signature... _Sigs>
struct completion_signatures
{
- template <class _Tag, class _Tuple, class _Variant>
- using __gather_sigs =
- __minvoke<__concat<_Variant>, __signal_args_t<_Sigs, _Tag, _Tuple>...>;
+ // Uncomment this to see where completion_signatures is
+ // erroneously getting instantiated:
+ // static_assert(sizeof...(_Sigs) == -1u);
};
+namespace __compl_sigs
+{
+template <class _TaggedTuple, __completion_tag _Tag, class... _Ts>
+auto __as_tagged_tuple_(_Tag (*)(_Ts...), _TaggedTuple*)
+ -> __mconst<__minvoke<_TaggedTuple, _Tag, _Ts...>>;
+
+template <class _Sig, class _TaggedTuple>
+using __as_tagged_tuple = decltype(__compl_sigs::__as_tagged_tuple_(
+ (_Sig*)nullptr, (_TaggedTuple*)nullptr));
+
+template <class _TaggedTuple, class _Variant, class... _Sigs>
+auto __for_all_sigs_(completion_signatures<_Sigs...>*, _TaggedTuple*, _Variant*)
+ -> __mconst<__minvoke<
+ _Variant, __minvoke<__as_tagged_tuple<_Sigs, _TaggedTuple>>...>>;
+
+template <class _Completions, class _TaggedTuple, class _Variant>
+using __for_all_sigs = __minvoke<decltype(__compl_sigs::__for_all_sigs_(
+ (_Completions*)nullptr, (_TaggedTuple*)nullptr, (_Variant*)nullptr))>;
+} // namespace __compl_sigs
+
template <class _Ty>
concept __is_completion_signatures =
__is_instance_of<_Ty, completion_signatures>;
@@ -421,7 +473,7 @@
template <__is_completion_signatures... _Completions>
struct __concat_completion_signatures<_Completions...>
{
- using __t = __minvoke<__concat<__munique<__q<completion_signatures>>>,
+ using __t = __minvoke<__mconcat<__munique<__q<completion_signatures>>>,
_Completions...>;
};
@@ -429,7 +481,7 @@
using __concat_completion_signatures_t =
__t<__concat_completion_signatures<_Completions...>>;
-template <class _Traits, class _Env>
+template <class _Completions, class _Env>
inline constexpr bool __valid_completion_signatures_ = false;
template <class... _Sigs, class _Env>
inline constexpr bool
@@ -439,9 +491,9 @@
inline constexpr bool __valid_completion_signatures_<
dependent_completion_signatures<no_env>, no_env> = true;
-template <class _Traits, class _Env>
+template <class _Completions, class _Env>
concept __valid_completion_signatures =
- __valid_completion_signatures_<_Traits, _Env>;
+ __valid_completion_signatures_<_Completions, _Env>;
/////////////////////////////////////////////////////////////////////////////
// [execution.receivers]
@@ -512,18 +564,19 @@
{
template <class _Sender, class _Env>
concept __with_tag_invoke =
- tag_invocable<get_completion_signatures_t, _Sender, _Env>;
+ __valid<tag_invoke_result_t, get_completion_signatures_t, _Sender, _Env>;
+
+template <class _Sender, class...>
+using __member_alias_t =
+ typename remove_cvref_t<_Sender>::completion_signatures;
template <class _Sender>
-concept __with_member_alias =
- requires { typename remove_cvref_t<_Sender>::completion_signatures; };
+concept __with_member_alias = __valid<__member_alias_t, _Sender>;
struct get_completion_signatures_t
{
- template <class _Sender, class _Env = no_env>
- requires(__with_tag_invoke<_Sender, _Env> ||
- __with_member_alias<_Sender> || __awaitable<_Sender, _Env>)
- constexpr auto operator()(_Sender&&, const _Env& = {}) const noexcept
+ template <class _Sender, class _Env>
+ static auto __impl()
{
static_assert(sizeof(_Sender),
"Incomplete type used with get_completion_signatures");
@@ -531,34 +584,42 @@
"Incomplete type used with get_completion_signatures");
if constexpr (__with_tag_invoke<_Sender, _Env>)
{
- using _Completions =
- tag_invoke_result_t<get_completion_signatures_t, _Sender, _Env>;
- return _Completions{};
+ return __mbind_front_q<tag_invoke_result_t,
+ get_completion_signatures_t>{};
}
else if constexpr (__with_member_alias<_Sender>)
{
- using _Completions =
- typename remove_cvref_t<_Sender>::completion_signatures;
- return _Completions{};
+ return __q<__member_alias_t>{};
}
- else
+ else if constexpr (__awaitable<_Sender, _Env>)
{
- // awaitables go here
using _Result = __await_result_t<_Sender, _Env>;
if constexpr (same_as<_Result,
dependent_completion_signatures<no_env>>)
{
- return dependent_completion_signatures<no_env>{};
+ return __mconst<dependent_completion_signatures<no_env>>{};
}
else
{
- return completion_signatures<
+ return __mconst<completion_signatures<
// set_value_t() or set_value_t(T)
- __minvoke1<__remove<void, __qf<set_value_t>>, _Result>,
- set_error_t(std::exception_ptr)>{};
+ __minvoke<__remove<void, __qf<set_value_t>>, _Result>,
+ set_error_t(std::exception_ptr)>>{};
}
}
}
+
+ template <class _Sender, class _Env>
+ using __impl_fn = decltype(__impl<_Sender, _Env>());
+
+ template <class _Sender, class _Env = no_env>
+ requires(__with_tag_invoke<_Sender, _Env> ||
+ __with_member_alias<_Sender> || __awaitable<_Sender, _Env>)
+ constexpr auto operator()(_Sender&&, const _Env& = {}) const noexcept
+ -> __minvoke<__impl_fn<_Sender, _Env>, _Sender, _Env>
+ {
+ return {};
+ }
};
} // namespace __get_completion_signatures
@@ -574,19 +635,17 @@
/////////////////////////////////////////////////////////////////////////////
// [execution.senders]
// NOT TO SPEC (YET)
-template <class _Sender, class _Env = no_env>
-concept sender =
- requires(_Sender&& __sndr, _Env&& __env) {
- get_completion_signatures((_Sender &&) __sndr, no_env{});
- get_completion_signatures((_Sender &&) __sndr, (_Env &&) __env);
- } &&
- __valid_completion_signatures<__completion_signatures_of_t<_Sender, no_env>,
- no_env> &&
+template <class _Sender, class _Env>
+concept __sender =
+ __valid<__completion_signatures_of_t, _Sender, _Env> &&
__valid_completion_signatures<__completion_signatures_of_t<_Sender, _Env>,
_Env> &&
move_constructible<remove_cvref_t<_Sender>> &&
constructible_from<remove_cvref_t<_Sender>, _Sender>;
+template <class _Sender, class _Env = no_env>
+concept sender = __sender<_Sender, no_env> && __sender<_Sender, _Env>;
+
// __checked_completion_signatures is for catching logic bugs in a typed
// sender's metadata. If sender<S> and sender<S, Ctx> are both true, then they
// had better report the same metadata. This completion signatures wrapper
@@ -616,7 +675,7 @@
template <class... _Ts>
using __variant =
__minvoke<__if_c<sizeof...(_Ts) != 0,
- __transform<__q1<decay_t>, __munique<__q<std::variant>>>,
+ __transform<__q<decay_t>, __munique<__q<std::variant>>>,
__mconst<__not_a_variant>>,
_Ts...>;
@@ -626,21 +685,39 @@
template <class... _Ts>
using __decayed_tuple = std::tuple<decay_t<_Ts>...>;
+template <class _Tag, class _Tuple>
+struct __select_completions_for
+{
+ template <same_as<_Tag> _Tag2, class... _Args>
+ using __f = __minvoke<_Tag2, _Tuple, _Args...>;
+};
+
+template <class _Tag, class _Tuple>
+using __select_completions_for_or =
+ __with_default<__select_completions_for<_Tag, _Tuple>, __>;
+
+template <class _Tag, class _Completions, class _Tuple, class _Variant>
+using __gather_signal =
+ __compl_sigs::__for_all_sigs<_Completions,
+ __select_completions_for_or<_Tag, _Tuple>,
+ __remove<__, _Variant>>;
+
template <class _Tag, class _Sender, class _Env, class _Tuple, class _Variant>
requires sender<_Sender, _Env>
-using __gather_sigs_t = typename completion_signatures_of_t<
- _Sender, _Env>::template __gather_sigs<_Tag, _Tuple, _Variant>;
+using __gather_completions_for =
+ __gather_signal<_Tag, completion_signatures_of_t<_Sender, _Env>, _Tuple,
+ _Variant>;
template <class _Sender, class _Env = no_env,
class _Tuple = __q<__decayed_tuple>, class _Variant = __q<__variant>>
requires sender<_Sender, _Env>
using __value_types_of_t =
- __gather_sigs_t<set_value_t, _Sender, _Env, _Tuple, _Variant>;
+ __gather_completions_for<set_value_t, _Sender, _Env, _Tuple, _Variant>;
template <class _Sender, class _Env = no_env, class _Variant = __q<__variant>>
requires sender<_Sender, _Env>
-using __error_types_of_t =
- __gather_sigs_t<set_error_t, _Sender, _Env, __q1<__id>, _Variant>;
+using __error_types_of_t = __gather_completions_for<set_error_t, _Sender, _Env,
+ __q<__midentity>, _Variant>;
template <class _Sender, class _Env = no_env,
template <class...> class _Tuple = __decayed_tuple,
@@ -657,7 +734,8 @@
template <class _Tag, class _Sender, class _Env = no_env>
requires sender<_Sender, _Env>
using __count_of =
- __gather_sigs_t<_Tag, _Sender, _Env, __mconst<int>, __mcount>;
+ __compl_sigs::__for_all_sigs<completion_signatures_of_t<_Sender, _Env>,
+ __q<__mfront>, __mcount<_Tag>>;
template <class _Tag, class _Sender, class _Env = no_env>
requires __valid<__count_of, _Tag, _Sender, _Env>
@@ -669,11 +747,11 @@
template <class _Sender, class _Env = no_env>
using __single_sender_value_t =
- __value_types_of_t<_Sender, _Env, __single_or<void>, __q<__single>>;
+ __value_types_of_t<_Sender, _Env, __msingle_or<void>, __q<__msingle>>;
template <class _Sender, class _Env = no_env>
using __single_value_variant_sender_t =
- value_types_of_t<_Sender, _Env, __types, __single>;
+ value_types_of_t<_Sender, _Env, __types, __msingle>;
template <class _Sender, class _Env = no_env>
concept __single_typed_sender = sender<_Sender, _Env> &&
@@ -702,7 +780,7 @@
template <__is_completion_signatures... _Sigs>
using __ensure_concat =
- __minvoke<__concat<__q<completion_signatures>>, _Sigs...>;
+ __minvoke<__mconcat<__q<completion_signatures>>, _Sigs...>;
template <class _Sender, class _Env, class _Sigs, class _SetValue,
class _SetError, class _SetStopped>
@@ -723,7 +801,7 @@
template <class _Sender, class _Env = no_env,
__valid_completion_signatures<_Env> _Sigs = completion_signatures<>,
class _SetValue = __q<__default_set_value>,
- class _SetError = __q1<__default_set_error>,
+ class _SetError = __q<__default_set_error>,
__valid_completion_signatures<_Env> _SetStopped =
completion_signatures<set_stopped_t()>>
requires sender<_Sender, _Env>
@@ -809,7 +887,7 @@
requires sender<_Sender, _Env>
using make_completion_signatures =
__make_completion_signatures<_Sender, _Env, _Sigs, __q<_SetValue>,
- __q1<_SetError>, _SetStopped>;
+ __q<_SetError>, _SetStopped>;
// Needed fairly often
using __with_exception_ptr =
@@ -907,11 +985,12 @@
constexpr __result_t<_T> operator()(_T&& __t) const
noexcept(noexcept(__result_t<_T>{}))
{
- using _Bool =
+ using _Boolean =
tag_invoke_result_t<__has_algorithm_customizations_t, __cref_t<_T>>;
- static_assert(
- _Bool{} ? true : true); // must be contextually convertible to bool
- return _Bool{};
+ static_assert(_Boolean{}
+ ? true
+ : true); // must be contextually convertible to bool
+ return _Boolean{};
}
constexpr std::false_type operator()(auto&&) const noexcept
{
@@ -964,7 +1043,7 @@
/////////////////////////////////////////////////////////////////////////////
// [execution.general.queries], general queries
-namespace __general_queries
+namespace __queries
{
// TODO: implement allocator concept
template <class _T0>
@@ -1035,11 +1114,11 @@
}
auto operator()() const noexcept;
};
-} // namespace __general_queries
-using __general_queries::get_allocator_t;
-using __general_queries::get_delegatee_scheduler_t;
-using __general_queries::get_scheduler_t;
-using __general_queries::get_stop_token_t;
+} // namespace __queries
+using __queries::get_allocator_t;
+using __queries::get_delegatee_scheduler_t;
+using __queries::get_scheduler_t;
+using __queries::get_stop_token_t;
inline constexpr get_scheduler_t get_scheduler{};
inline constexpr get_delegatee_scheduler_t get_delegatee_scheduler{};
inline constexpr get_allocator_t get_allocator{};
@@ -1049,6 +1128,10 @@
using stop_token_of_t =
remove_cvref_t<decltype(get_stop_token(__declval<_T>()))>;
+template <receiver _Receiver>
+using __current_scheduler_t =
+ __call_result_t<get_scheduler_t, env_of_t<_Receiver>>;
+
template <class _SchedulerProvider>
concept __scheduler_provider = requires(const _SchedulerProvider& __sp) {
{
@@ -1170,64 +1253,72 @@
struct __promise;
template <class _ReceiverId>
-struct __operation : __operation_base
+struct __operation
{
- using promise_type = __promise<_ReceiverId>;
- using __operation_base::__operation_base;
+ struct __t : __operation_base
+ {
+ using promise_type = stdexec::__t<__promise<_ReceiverId>>;
+ using __operation_base::__operation_base;
+ };
};
template <class _ReceiverId>
-struct __promise : __promise_base
+struct __promise
{
- using _Receiver = __t<_ReceiverId>;
+ using _Receiver = stdexec::__t<_ReceiverId>;
- explicit __promise(auto&, _Receiver& __rcvr) noexcept : __rcvr_(__rcvr) {}
-
- __coro::coroutine_handle<> unhandled_stopped() noexcept
+ struct __t : __promise_base
{
- set_stopped(std::move(__rcvr_));
- // Returning noop_coroutine here causes the __connect_awaitable
- // coroutine to never resume past the point where it co_await's
- // the awaitable.
- return __coro::noop_coroutine();
- }
+ using __id = __promise;
- __operation<_ReceiverId> get_return_object() noexcept
- {
- return __operation<_ReceiverId>{
- __coro::coroutine_handle<__promise>::from_promise(*this)};
- }
+ explicit __t(auto&, _Receiver& __rcvr) noexcept : __rcvr_(__rcvr) {}
- template <class _Awaitable>
- _Awaitable&& await_transform(_Awaitable&& __await) noexcept
- {
- return (_Awaitable &&) __await;
- }
+ __coro::coroutine_handle<> unhandled_stopped() noexcept
+ {
+ set_stopped(std::move(__rcvr_));
+ // Returning noop_coroutine here causes the __connect_awaitable
+ // coroutine to never resume past the point where it co_await's
+ // the awaitable.
+ return __coro::noop_coroutine();
+ }
- template <class _Awaitable>
- requires tag_invocable<as_awaitable_t, _Awaitable, __promise&>
- auto await_transform(_Awaitable&& __await) noexcept(
- nothrow_tag_invocable<as_awaitable_t, _Awaitable, __promise&>)
- -> tag_invoke_result_t<as_awaitable_t, _Awaitable, __promise&>
- {
- return tag_invoke(as_awaitable, (_Awaitable &&) __await, *this);
- }
+ stdexec::__t<__operation<_ReceiverId>> get_return_object() noexcept
+ {
+ return stdexec::__t<__operation<_ReceiverId>>{
+ __coro::coroutine_handle<__t>::from_promise(*this)};
+ }
- // Pass through the get_env receiver query
- friend auto tag_invoke(get_env_t, const __promise& __self)
- -> env_of_t<_Receiver>
- {
- return get_env(__self.__rcvr_);
- }
+ template <class _Awaitable>
+ _Awaitable&& await_transform(_Awaitable&& __await) noexcept
+ {
+ return (_Awaitable &&) __await;
+ }
- _Receiver& __rcvr_;
+ template <class _Awaitable>
+ requires tag_invocable<as_awaitable_t, _Awaitable, __t&>
+ auto await_transform(_Awaitable&& __await) noexcept(
+ nothrow_tag_invocable<as_awaitable_t, _Awaitable, __t&>)
+ -> tag_invoke_result_t<as_awaitable_t, _Awaitable, __t&>
+ {
+ return tag_invoke(as_awaitable, (_Awaitable &&) __await, *this);
+ }
+
+ // Pass through the get_env receiver query
+ friend auto tag_invoke(get_env_t, const __t& __self)
+ -> env_of_t<_Receiver>
+ {
+ return get_env(__self.__rcvr_);
+ }
+
+ _Receiver& __rcvr_;
+ };
};
template <receiver _Receiver>
-using __promise_t = __promise<__x<remove_cvref_t<_Receiver>>>;
+using __promise_t = __t<__promise<__id<_Receiver>>>;
template <receiver _Receiver>
-using __operation_t = __operation<__x<remove_cvref_t<_Receiver>>>;
+using __operation_t = __t<__operation<__id<_Receiver>>>;
struct __connect_awaitable_t
{
@@ -1270,7 +1361,7 @@
template <receiver _Receiver, class _Awaitable>
using __completions_t = completion_signatures<
- __minvoke1< // set_value_t() or set_value_t(T)
+ __minvoke< // set_value_t() or set_value_t(T)
__remove<void, __qf<set_value_t>>,
__await_result_t<_Awaitable, __promise_t<_Receiver>>>,
set_error_t(std::exception_ptr), set_stopped_t()>;
@@ -1279,7 +1370,7 @@
template <class _Receiver, __awaitable<__promise_t<_Receiver>> _Awaitable>
requires receiver_of<_Receiver, __completions_t<_Receiver, _Awaitable>>
__operation_t<_Receiver> operator()(_Awaitable&& __await,
- _Receiver&& __rcvr) const
+ _Receiver __rcvr) const
{
return __co_impl((_Awaitable &&) __await, (_Receiver &&) __rcvr);
}
@@ -1326,7 +1417,7 @@
void operator()(_Env&&) const noexcept;
};
template <class _Env>
-using __debug_env_t = __make_env_t<_Env, __with_t<__is_debug_env_t, bool>>;
+using __debug_env_t = __make_env_t<_Env, __with<__is_debug_env_t, bool>>;
struct __debug_op_state
{
@@ -1357,10 +1448,12 @@
template <class _Env>
struct __any_debug_receiver
{
+ template <class... _Args>
friend void tag_invoke(set_value_t, __any_debug_receiver&&,
- auto&&...) noexcept;
+ _Args&&...) noexcept;
+ template <class _Error>
friend void tag_invoke(set_error_t, __any_debug_receiver&&,
- auto&&) noexcept;
+ _Error&&) noexcept;
friend void tag_invoke(set_stopped_t, __any_debug_receiver&&) noexcept;
friend __debug_env_t<_Env> tag_invoke(get_env_t,
__any_debug_receiver) noexcept;
@@ -1548,9 +1641,9 @@
template <class _Sender, class _SetSig, class _Env = no_env>
concept sender_of =
sender<_Sender, _Env> &&
- same_as<__types<_SetSig>,
- __gather_sigs_t<__tag_of_sig_t<_SetSig>, _Sender, _Env,
- __qf<__tag_of_sig_t<_SetSig>>, __q<__types>>>;
+ same_as<__types<_SetSig>, __gather_completions_for<
+ __tag_of_sig_t<_SetSig>, _Sender, _Env,
+ __qf<__tag_of_sig_t<_SetSig>>, __q<__types>>>;
/////////////////////////////////////////////////////////////////////////////
// [exec.snd_queries], sender queries
@@ -1606,8 +1699,6 @@
// stdexec::as_awaitable [execution.coro_utils.as_awaitable]
namespace __as_awaitable
{
-namespace __impl
-{
struct __void
{};
template <class _Value>
@@ -1653,12 +1744,13 @@
};
template <class _PromiseId, class _Value>
-struct __sender_awaitable_base
+struct __receiver
{
- using _Promise = __t<_PromiseId>;
- struct __receiver : __receiver_base<_Value>
+ using _Promise = stdexec::__t<_PromiseId>;
+ struct __t : __receiver_base<_Value>
{
- friend void tag_invoke(set_stopped_t, __receiver&& __self) noexcept
+ using __id = __receiver;
+ friend void tag_invoke(set_stopped_t, __t&& __self) noexcept
{
auto __continuation =
__coro::coroutine_handle<_Promise>::from_address(
@@ -1669,7 +1761,7 @@
}
// Forward get_env query to the coroutine promise
- friend auto tag_invoke(get_env_t, const __receiver& __self)
+ friend auto tag_invoke(get_env_t, const __t& __self)
-> env_of_t<_Promise>
{
auto __continuation =
@@ -1678,7 +1770,18 @@
return get_env(__continuation.promise());
}
};
+};
+template <class _Sender, class _Promise>
+using __value_t = __single_sender_value_t<_Sender, env_of_t<_Promise>>;
+
+template <class _Sender, class _Promise>
+using __receiver_t =
+ __t<__receiver<__id<_Promise>, __value_t<_Sender, _Promise>>>;
+
+template <class _Value>
+struct __sender_awaitable_base
+{
bool await_ready() const noexcept
{
return false;
@@ -1707,36 +1810,35 @@
};
template <class _PromiseId, class _SenderId>
-struct __sender_awaitable :
- __sender_awaitable_base<
- _PromiseId,
- __single_sender_value_t<__t<_SenderId>, env_of_t<__t<_PromiseId>>>>
+struct __sender_awaitable
{
- private:
- using _Promise = __t<_PromiseId>;
- using _Sender = __t<_SenderId>;
- using _Env = env_of_t<_Promise>;
- using _Value = __single_sender_value_t<_Sender, _Env>;
- using _Base = __sender_awaitable_base<_PromiseId, _Value>;
- using __receiver = typename _Base::__receiver;
- connect_result_t<_Sender, __receiver> __op_state_;
-
- public:
- __sender_awaitable(
- _Sender&& sender,
- __coro::coroutine_handle<_Promise>
- __hcoro) noexcept(__nothrow_connectable<_Sender, __receiver>) :
- __op_state_(connect((_Sender &&) sender,
- __receiver{{&this->__result_, __hcoro}}))
- {}
-
- void await_suspend(__coro::coroutine_handle<_Promise>) noexcept
+ using _Promise = stdexec::__t<_PromiseId>;
+ using _Sender = stdexec::__t<_SenderId>;
+ using __value =
+ __value_t<stdexec::__t<_SenderId>, stdexec::__t<_PromiseId>>;
+ struct __t : __sender_awaitable_base<__value>
{
- start(__op_state_);
- }
+ __t(_Sender&& sndr,
+ __coro::coroutine_handle<_Promise>
+ __hcoro) noexcept(__nothrow_connectable<_Sender, __receiver>) :
+ __op_state_(connect((_Sender &&) sndr,
+ __receiver{{&this->__result_, __hcoro}}))
+ {}
+
+ void await_suspend(__coro::coroutine_handle<_Promise>) noexcept
+ {
+ start(__op_state_);
+ }
+
+ private:
+ using __receiver = __receiver_t<_Sender, _Promise>;
+ connect_result_t<_Sender, __receiver> __op_state_;
+ };
};
+
template <class _Promise, class _Sender>
-using __sender_awaitable_t = __sender_awaitable<__x<_Promise>, __x<_Sender>>;
+using __sender_awaitable_t =
+ __t<__sender_awaitable<__id<_Promise>, __id<_Sender>>>;
template <class _T, class _Promise>
concept __custom_tag_invoke_awaiter =
@@ -1744,27 +1846,21 @@
__awaitable<tag_invoke_result_t<as_awaitable_t, _T, _Promise&>, _Promise>;
template <class _Sender, class _Promise>
-using __receiver = typename __sender_awaitable_base<
- __x<_Promise>,
- __single_sender_value_t<_Sender, env_of_t<_Promise>>>::__receiver;
-
-template <class _Sender, class _Promise>
concept __awaitable_sender =
__single_typed_sender<_Sender, env_of_t<_Promise>> &&
- sender_to<_Sender, __receiver<_Sender, _Promise>> &&
+ sender_to<_Sender, __receiver_t<_Sender, _Promise>> &&
requires(_Promise& __promise) {
{
__promise.unhandled_stopped()
} -> convertible_to<__coro::coroutine_handle<>>;
};
-} // namespace __impl
struct as_awaitable_t
{
template <class _T, class _Promise>
static constexpr bool __is_noexcept() noexcept
{
- if constexpr (__impl::__custom_tag_invoke_awaiter<_T, _Promise>)
+ if constexpr (__custom_tag_invoke_awaiter<_T, _Promise>)
{
return nothrow_tag_invocable<as_awaitable_t, _T, _Promise&>;
}
@@ -1772,9 +1868,9 @@
{
return true;
}
- else if constexpr (__impl::__awaitable_sender<_T, _Promise>)
+ else if constexpr (__awaitable_sender<_T, _Promise>)
{
- using _Sender = __impl::__sender_awaitable_t<_Promise, _T>;
+ using _Sender = __sender_awaitable_t<_Promise, _T>;
return std::is_nothrow_constructible_v<
_Sender, _T, __coro::coroutine_handle<_Promise>>;
}
@@ -1787,7 +1883,7 @@
decltype(auto) operator()(_T&& __t, _Promise& __promise) const
noexcept(__is_noexcept<_T, _Promise>())
{
- if constexpr (__impl::__custom_tag_invoke_awaiter<_T, _Promise>)
+ if constexpr (__custom_tag_invoke_awaiter<_T, _Promise>)
{
return tag_invoke(*this, (_T &&) __t, __promise);
}
@@ -1795,12 +1891,11 @@
{
return (_T &&) __t;
}
- else if constexpr (__impl::__awaitable_sender<_T, _Promise>)
+ else if constexpr (__awaitable_sender<_T, _Promise>)
{
auto __hcoro =
__coro::coroutine_handle<_Promise>::from_promise(__promise);
- return __impl::__sender_awaitable_t<_Promise, _T>{(_T &&) __t,
- __hcoro};
+ return __sender_awaitable_t<_Promise, _T>{(_T &&) __t, __hcoro};
}
else
{
@@ -1814,8 +1909,6 @@
namespace __with_awaitable_senders
{
-namespace __impl
-{
struct __with_awaitable_senders_base
{
template <class _OtherPromise>
@@ -1859,10 +1952,9 @@
__coro::coroutine_handle<> (*__stopped_callback_)(void*) noexcept =
[](void*) noexcept -> __coro::coroutine_handle<> { std::terminate(); };
};
-} // namespace __impl
template <class _Promise>
-struct with_awaitable_senders : __impl::__with_awaitable_senders_base
+struct with_awaitable_senders : __with_awaitable_senders_base
{
template <class _Value>
auto await_transform(_Value&& __val)
@@ -1880,16 +1972,18 @@
// NOT TO SPEC: __submit
namespace __submit_
{
-namespace __impl
-{
template <class _SenderId, class _ReceiverId>
struct __operation
{
- using _Sender = __t<_SenderId>;
- using _Receiver = __t<_ReceiverId>;
+ using _Sender = stdexec::__t<_SenderId>;
+ using _Receiver = stdexec::__t<_ReceiverId>;
+ struct __t;
+
struct __receiver
{
- __operation* __op_state_;
+ using __t = __receiver;
+ using __id = __receiver;
+ __operation::__t* __op_state_;
// Forward all the receiver ops, and delete the operation state.
template <__one_of<set_value_t, set_error_t, set_stopped_t> _Tag,
class... _As>
@@ -1899,7 +1993,7 @@
_As&&... __as) noexcept(__nothrow_callable<_Tag, _Receiver, _As...>)
{
// Delete the state as cleanup:
- std::unique_ptr<__operation> __g{__self.__op_state_};
+ std::unique_ptr<__operation::__t> __g{__self.__op_state_};
return __tag((_Receiver &&) __self.__op_state_->__rcvr_,
(_As &&) __as...);
}
@@ -1910,22 +2004,25 @@
return get_env((const _Receiver&)__self.__op_state_->__rcvr_);
}
};
- _Receiver __rcvr_;
- connect_result_t<_Sender, __receiver> __op_state_;
- template <__decays_to<_Receiver> _CvrefReceiver>
- __operation(_Sender&& __sndr, _CvrefReceiver&& __rcvr) :
- __rcvr_((_CvrefReceiver &&) __rcvr),
- __op_state_(connect((_Sender &&) __sndr, __receiver{this}))
- {}
+
+ struct __t
+ {
+ using __id = __operation;
+ _Receiver __rcvr_;
+ connect_result_t<_Sender, __receiver> __op_state_;
+ __t(_Sender&& __sndr, _Receiver&& __rcvr) :
+ __rcvr_((_Receiver &&) __rcvr),
+ __op_state_(connect((_Sender &&) __sndr, __receiver{this}))
+ {}
+ };
};
-} // namespace __impl
struct __submit_t
{
template <receiver _Receiver, sender_to<_Receiver> _Sender>
- void operator()(_Sender&& __sndr, _Receiver&& __rcvr) const noexcept(false)
+ void operator()(_Sender&& __sndr, _Receiver __rcvr) const noexcept(false)
{
- start((new __impl::__operation<__x<_Sender>, __x<decay_t<_Receiver>>>{
+ start((new __t<__operation<__id<_Sender>, __id<_Receiver>>>{
(_Sender &&) __sndr, (_Receiver &&) __rcvr})
->__op_state_);
}
@@ -1938,6 +2035,8 @@
{
struct __scheduler
{
+ using __t = __scheduler;
+ using __id = __scheduler;
template <class _Receiver>
struct __op : __immovable
{
@@ -1950,12 +2049,13 @@
struct __sender
{
+ using __t = __sender;
+ using __id = __sender;
using completion_signatures =
stdexec::completion_signatures<set_value_t()>;
template <typename _Receiver>
- friend __op<_Receiver> tag_invoke(connect_t, __sender,
- _Receiver&& __rcvr)
+ friend __op<_Receiver> tag_invoke(connect_t, __sender, _Receiver __rcvr)
{
return {{}, (_Receiver &&) __rcvr};
}
@@ -1984,89 +2084,76 @@
template <class _EnvId>
struct __detached_receiver
{
- using _Env = __t<_EnvId>;
- [[no_unique_address]] _Env __env_;
- template <class... _As>
- friend void tag_invoke(set_value_t, __detached_receiver&&,
- _As&&...) noexcept
- {}
- template <class _Error>
- [[noreturn]] friend void tag_invoke(set_error_t, __detached_receiver&&,
- _Error&&) noexcept
+ using _Env = stdexec::__t<_EnvId>;
+ struct __t
{
- std::terminate();
- }
- friend void tag_invoke(set_stopped_t, __detached_receiver&&) noexcept {}
- friend const _Env& tag_invoke(get_env_t,
- const __detached_receiver& __self) noexcept
- {
- // BUGBUG NOT TO SPEC
- return __self.__env_;
- }
+ using __id = __detached_receiver;
+ [[no_unique_address]] _Env __env_;
+ template <class... _As>
+ friend void tag_invoke(set_value_t, __t&&, _As&&...) noexcept
+ {}
+ template <class _Error>
+ [[noreturn]] friend void tag_invoke(set_error_t, __t&&,
+ _Error&&) noexcept
+ {
+ std::terminate();
+ }
+ friend void tag_invoke(set_stopped_t, __t&&) noexcept {}
+ friend const _Env& tag_invoke(get_env_t, const __t& __self) noexcept
+ {
+ // BUGBUG NOT TO SPEC
+ return __self.__env_;
+ }
+ };
};
template <class _Env>
-__detached_receiver(_Env) -> __detached_receiver<__x<_Env>>;
+using __detached_receiver_t =
+ __t<__detached_receiver<__id<remove_cvref_t<_Env>>>>;
struct start_detached_t;
// When looking for user-defined customizations of start_detached, these
// are the signatures to test against, in order:
-template <class _Sender, class _Env>
-using __cust_sigs = __msignatures<
- tag_invoke_t(start_detached_t, _Sender),
- tag_invoke_t(start_detached_t, _Sender, _Env),
- tag_invoke_t(start_detached_t, get_scheduler_t(_Env&), _Sender),
- tag_invoke_t(start_detached_t, get_scheduler_t(_Env&), _Sender, _Env)>;
+using _Sender = __0;
+using _Env = __1;
+using __cust_sigs =
+ __types<tag_invoke_t(start_detached_t, _Sender),
+ tag_invoke_t(start_detached_t, _Sender, _Env),
+ tag_invoke_t(start_detached_t, get_scheduler_t(_Env&), _Sender),
+ tag_invoke_t(start_detached_t, get_scheduler_t(_Env&), _Sender,
+ _Env)>;
template <class _Sender, class _Env>
inline constexpr bool __is_start_detached_customized =
- __v<__many_well_formed<__cust_sigs<_Sender, _Env>>>;
+ __minvocable<__which<__cust_sigs>, _Sender, _Env>;
+
+struct __submit_detached
+{
+ template <class _Sender, class _Env>
+ void operator()(_Sender&& __sndr, _Env&& __env) const
+ {
+ __submit((_Sender &&) __sndr,
+ __detached_receiver_t<_Env>{(_Env &&) __env});
+ }
+};
template <class _Sender, class _Env>
-using __which_t =
- __mwhich_t<__cust_sigs<_Sender, _Env>, __mconstruct<void, false>()>;
-
-template <class _Sender, class _Env>
-using __which_i =
- __mwhich_i<__cust_sigs<_Sender, _Env>, __mconstruct<void, false>()>;
+using __dispatcher_for =
+ __make_dispatcher<__cust_sigs, __mconst<__submit_detached>, _Sender, _Env>;
struct start_detached_t
{
template <sender _Sender, class _Env = __empty_env>
- requires sender_to<_Sender,
- __detached_receiver<__x<remove_cvref_t<_Env>>>> ||
+ requires sender_to<_Sender, __detached_receiver_t<_Env>> ||
__is_start_detached_customized<_Sender, _Env>
- void operator()(_Sender&& __sndr, _Env&& __env = _Env{}) const
- noexcept(__mnoexcept_v<__which_t<_Sender, _Env>>)
+ void operator()(_Sender&& __sndr, _Env&& __env = _Env{}) const noexcept(
+ __nothrow_callable<__dispatcher_for<_Sender, _Env>, _Sender, _Env>)
{
- // The selected customization should return void
- static_assert(same_as<void, __mtypeof<__which_t<_Sender, _Env>>>);
- constexpr auto __idx = __v<__which_i<_Sender, _Env>>;
- // Dispatch to the correct implementation:
- if constexpr (__idx == 0)
- {
- tag_invoke(start_detached_t{}, (_Sender &&) __sndr);
- }
- else if constexpr (__idx == 1)
- {
- tag_invoke(start_detached_t{}, (_Sender &&) __sndr,
- (_Env &&) __env);
- }
- else if constexpr (__idx == 2)
- {
- tag_invoke(start_detached_t{}, get_scheduler(__env),
- (_Sender &&) __sndr);
- }
- else if constexpr (__idx == 3)
- {
- auto __sched = get_scheduler(__env);
- tag_invoke(start_detached_t{}, std::move(__sched),
- (_Sender &&) __sndr, (_Env &&) __env);
- }
- else
- {
- __submit((_Sender &&) __sndr, __detached_receiver{(_Env &&) __env});
- }
+ using _Dispatcher = __dispatcher_for<_Sender, _Env>;
+ // The selected implementation should return void
+ static_assert(
+ same_as<void, __call_result_t<_Dispatcher, _Sender, _Env>>);
+ _Dispatcher{}((_Sender &&) __sndr, (_Env &&) __env);
}
};
} // namespace __start_detached
@@ -2077,78 +2164,114 @@
// [execution.senders.factories]
namespace __just
{
+template <class _Tag, class... _Ts>
+using __completion_signatures_ = completion_signatures<_Tag(_Ts...)>;
-template <class _CPO, class... _Ts>
-using __completion_signatures_ = completion_signatures<_CPO(_Ts...)>;
-
-template <class _CPO, class... _Ts>
-struct __sender
+template <class _ReceiverId, class _Tag, class... _Ts>
+struct __operation
{
- std::tuple<_Ts...> __vals_;
-
- using completion_signatures = __completion_signatures_<_CPO, _Ts...>;
-
- template <class _ReceiverId>
- struct __operation : __immovable
+ using _Receiver = stdexec::__t<_ReceiverId>;
+ struct __t : __immovable
{
- using _Receiver = __t<_ReceiverId>;
+ using __id = __operation;
std::tuple<_Ts...> __vals_;
_Receiver __rcvr_;
- friend void tag_invoke(start_t, __operation& __op_state) noexcept
+ friend void tag_invoke(start_t, __t& __op_state) noexcept
{
std::apply(
[&__op_state](_Ts&... __ts) {
- _CPO{}((_Receiver &&) __op_state.__rcvr_, (_Ts &&) __ts...);
+ _Tag{}((_Receiver &&) __op_state.__rcvr_, (_Ts &&) __ts...);
},
__op_state.__vals_);
}
};
+};
- template <receiver_of<completion_signatures> _Receiver>
- requires(copy_constructible<_Ts> && ...)
- friend auto tag_invoke(
- connect_t, const __sender& __sndr,
- _Receiver&&
- __rcvr) noexcept((std::is_nothrow_copy_constructible_v<_Ts> && ...))
- -> __operation<__x<remove_cvref_t<_Receiver>>>
- {
- return {{}, __sndr.__vals_, (_Receiver &&) __rcvr};
- }
+template <class _Tag, class... _Ts>
+struct __basic_sender
+{
+ template <class _Receiver>
+ using __operation_t =
+ stdexec::__t<__operation<stdexec::__id<_Receiver>, _Tag, _Ts...>>;
- template <receiver_of<completion_signatures> _Receiver>
- friend auto
- tag_invoke(connect_t, __sender&& __sndr, _Receiver&& __rcvr) noexcept(
- (std::is_nothrow_move_constructible_v<_Ts> && ...))
- -> __operation<__x<remove_cvref_t<_Receiver>>>
+ struct __t
{
- return {{}, ((__sender &&) __sndr).__vals_, (_Receiver &&) __rcvr};
- }
+ using __id = __basic_sender;
+ using completion_signatures = __completion_signatures_<_Tag, _Ts...>;
+ std::tuple<_Ts...> __vals_;
+
+ template <receiver_of<completion_signatures> _Receiver>
+ requires(copy_constructible<_Ts> && ...)
+ friend auto tag_invoke(
+ connect_t, const __t& __sndr,
+ _Receiver
+ __rcvr) noexcept((std::is_nothrow_copy_constructible_v<_Ts> &&
+ ...)) -> __operation_t<_Receiver>
+ {
+ return {{}, __sndr.__vals_, (_Receiver &&) __rcvr};
+ }
+
+ template <receiver_of<completion_signatures> _Receiver>
+ friend auto
+ tag_invoke(connect_t, __t&& __sndr, _Receiver __rcvr) noexcept(
+ (std::is_nothrow_move_constructible_v<_Ts> && ...))
+ -> __operation_t<_Receiver>
+ {
+ return {{}, ((__t &&) __sndr).__vals_, (_Receiver &&) __rcvr};
+ }
+ };
+};
+
+template <class... _Values>
+struct __sender
+{
+ using __base = stdexec::__t<__basic_sender<set_value_t, _Values...>>;
+ struct __t : __base
+ {
+ using __id = __sender;
+ };
+};
+
+template <class _Error>
+struct __error_sender
+{
+ using __base = stdexec::__t<__basic_sender<set_error_t, _Error>>;
+ struct __t : __base
+ {
+ using __id = __error_sender;
+ };
+};
+
+struct __stopped_sender : __t<__basic_sender<set_stopped_t>>
+{
+ using __id = __stopped_sender;
+ using __t = __stopped_sender;
};
inline constexpr struct __just_t
{
template <__movable_value... _Ts>
- __sender<set_value_t, decay_t<_Ts>...> operator()(_Ts&&... __ts) const
+ __t<__sender<decay_t<_Ts>...>> operator()(_Ts&&... __ts) const
noexcept((std::is_nothrow_constructible_v<decay_t<_Ts>, _Ts> && ...))
{
- return {{(_Ts &&) __ts...}};
+ return {{{(_Ts &&) __ts...}}};
}
} just{};
inline constexpr struct __just_error_t
{
template <__movable_value _Error>
- __sender<set_error_t, decay_t<_Error>> operator()(_Error&& __err) const
+ __t<__error_sender<decay_t<_Error>>> operator()(_Error&& __err) const
noexcept(std::is_nothrow_constructible_v<decay_t<_Error>, _Error>)
{
- return {{(_Error &&) __err}};
+ return {{{(_Error &&) __err}}};
}
} just_error{};
inline constexpr struct __just_stopped_t
{
- __sender<set_stopped_t> operator()() const noexcept
+ __stopped_sender operator()() const noexcept
{
return {{}};
}
@@ -2162,8 +2285,6 @@
// [execution.execute]
namespace __execute_
{
-namespace __impl
-{
template <class _Fun>
struct __as_receiver
{
@@ -2188,7 +2309,6 @@
return {};
}
};
-} // namespace __impl
struct execute_t
{
@@ -2196,11 +2316,10 @@
requires __callable<_Fun&> && move_constructible<_Fun>
void operator()(_Scheduler&& __sched, _Fun __fun) const
noexcept(noexcept(__submit(schedule((_Scheduler &&) __sched),
- __impl::__as_receiver<_Fun>{(_Fun &&)
- __fun})))
+ __as_receiver<_Fun>{(_Fun &&) __fun})))
{
(void)__submit(schedule((_Scheduler &&) __sched),
- __impl::__as_receiver<_Fun>{(_Fun &&) __fun});
+ __as_receiver<_Fun>{(_Fun &&) __fun});
}
template <scheduler _Scheduler, class _Fun>
requires __callable<_Fun&> && move_constructible<_Fun> &&
@@ -2267,13 +2386,6 @@
struct sender_adaptor_closure
{};
-template <__sender_adaptor_closure _T0, __sender_adaptor_closure _T1>
-__compose<remove_cvref_t<_T0>, remove_cvref_t<_T1>> operator|(_T0&& __t0,
- _T1&& __t1)
-{
- return {{}, (_T0 &&) __t0, (_T1 &&) __t1};
-}
-
template <sender _Sender, __sender_adaptor_closure_for<_Sender> _Closure>
__call_result_t<_Closure, _Sender> operator|(_Sender&& __sndr,
_Closure&& __clsur)
@@ -2281,6 +2393,13 @@
return ((_Closure &&) __clsur)((_Sender &&) __sndr);
}
+template <__sender_adaptor_closure _T0, __sender_adaptor_closure _T1>
+__compose<remove_cvref_t<_T0>, remove_cvref_t<_T1>> operator|(_T0&& __t0,
+ _T1&& __t1)
+{
+ return {{}, (_T0 &&) __t0, (_T1 &&) __t1};
+}
+
template <class _Fun, class... _As>
struct __binder_back : sender_adaptor_closure<__binder_back<_Fun, _As...>>
{
@@ -2321,12 +2440,12 @@
// A derived-to-base cast that works even when the base is not
// accessible from derived.
template <class _T, class _U>
-__member_t<_U, _T> __c_cast(_U&& u) noexcept
+__copy_cvref_t<_U&&, _T> __c_cast(_U&& u) noexcept
requires __decays_to<_T, _T>
{
- static_assert(std::is_reference_v<__member_t<_U, _T>>);
+ static_assert(std::is_reference_v<__copy_cvref_t<_U&&, _T>>);
static_assert(std::is_base_of_v<_T, std::remove_reference_t<_U>>);
- return (__member_t<_U, _T>)(_U &&) u;
+ return (__copy_cvref_t<_U&&, _T>)(_U &&) u;
}
namespace __no
{
@@ -2408,64 +2527,6 @@
static constexpr int _TAG = 1 /**/
#endif
-template <__class _Derived, sender _Base>
-struct sender_adaptor
-{
- class __t : __adaptor_base<_Base>
- {
- _DEFINE_MEMBER(connect);
-
- template <same_as<connect_t> _Connect, __decays_to<_Derived> _Self,
- receiver _Receiver>
- friend auto
- tag_invoke(_Connect, _Self&& __self, _Receiver&& __rcvr) noexcept(
- noexcept(_CALL_MEMBER(connect, (_Self &&) __self,
- (_Receiver &&) __rcvr)))
- -> decltype(_CALL_MEMBER(connect, (_Self &&) __self,
- (_Receiver &&) __rcvr))
- {
- return _CALL_MEMBER(connect, (_Self &&) __self,
- (_Receiver &&) __rcvr);
- }
-
- template <same_as<connect_t> _Connect, __decays_to<_Derived> _Self,
- receiver _Receiver>
- requires _MISSING_MEMBER(decay_t<_Self>, connect) &&
- sender_to<__member_t<_Self, _Base>, _Receiver>
- friend auto tag_invoke(
- _Connect, _Self&& __self,
- _Receiver&&
- __rcvr) noexcept(__nothrow_connectable<__member_t<_Self,
- _Base>,
- _Receiver>)
- -> connect_result_t<__member_t<_Self, _Base>,
- _Receiver>
- {
- return stdexec::connect(((__t &&) __self).base(),
- (_Receiver &&) __rcvr);
- }
-
- template <tag_category<forwarding_sender_query> _Tag, class... _As>
- requires __callable<_Tag, const _Base&, _As...>
- friend auto tag_invoke(
- _Tag __tag, const _Derived& __self,
- _As&&... __as) noexcept(__nothrow_callable<_Tag, const _Base&,
- _As...>)
- -> __call_result_if_t<tag_category<_Tag, forwarding_sender_query>,
- _Tag, const _Base&, _As...>
- {
- return ((_Tag &&) __tag)(__self.base(), (_As &&) __as...);
- }
-
- protected:
- using __adaptor_base<_Base>::base;
-
- public:
- __t() = default;
- using __adaptor_base<_Base>::__adaptor_base;
- };
-};
-
template <__class _Derived, class _Base>
struct receiver_adaptor
{
@@ -2483,11 +2544,11 @@
using __base_from_derived_t = decltype(__declval<_D>().base());
using __get_base_t =
- __if_c<__has_base, __mbind_back_q1<__member_t, _Base>,
- __q1<__base_from_derived_t>>;
+ __if_c<__has_base, __mbind_back_q<__copy_cvref_t, _Base>,
+ __q<__base_from_derived_t>>;
template <class _D>
- using __base_t = __minvoke1<__get_base_t, _D&&>;
+ using __base_t = __minvoke<__get_base_t, _D&&>;
template <class _D>
static __base_t<_D> __get_base(_D&& __self) noexcept
@@ -2583,120 +2644,12 @@
using __adaptor_base<_Base>::__adaptor_base;
};
};
-
-template <__class _Derived, operation_state _Base>
-struct operation_state_adaptor
-{
- class __t : __adaptor_base<_Base>, __immovable
- {
- _DEFINE_MEMBER(start);
-
- template <same_as<start_t> _Start, class _D = _Derived>
- friend auto tag_invoke(_Start, _Derived& __self) noexcept
- -> decltype(_CALL_MEMBER(start, (_D&)__self))
- {
- static_assert(noexcept(_CALL_MEMBER(start, (_D&)__self)));
- _CALL_MEMBER(start, (_D&)__self);
- }
-
- template <same_as<start_t> _Start, class _D = _Derived>
- requires _MISSING_MEMBER(_D, start)
- friend void tag_invoke(_Start, _Derived& __self) noexcept
- {
- stdexec::start(__c_cast<__t>(__self).base());
- }
-
- template <__none_of<start_t> _Tag, class... _As>
- requires __callable<_Tag, const _Base&, _As...>
- friend auto tag_invoke(
- _Tag __tag, const _Derived& __self,
- _As&&... __as) noexcept(__nothrow_callable<_Tag, const _Base&,
- _As...>)
- -> __call_result_if_t<__none_of<_Tag, start_t>, _Tag, const _Base&,
- _As...>
- {
- return ((_Tag &&) __tag)(__c_cast<__t>(__self).base(),
- (_As &&) __as...);
- }
-
- protected:
- using __adaptor_base<_Base>::base;
-
- public:
- __t() = default;
- using __adaptor_base<_Base>::__adaptor_base;
- };
-};
-
-template <__class _Derived, scheduler _Base>
-struct scheduler_adaptor
-{
- class __t : __adaptor_base<_Base>
- {
- _DEFINE_MEMBER(schedule);
-
- template <same_as<schedule_t> _Schedule, __decays_to<_Derived> _Self>
- friend auto tag_invoke(_Schedule, _Self&& __self) noexcept(
- noexcept(_CALL_MEMBER(schedule, (_Self &&) __self)))
- -> decltype(_CALL_MEMBER(schedule, (_Self &&) __self))
- {
- return _CALL_MEMBER(schedule, (_Self &&) __self);
- }
-
- template <same_as<schedule_t> _Schedule, __decays_to<_Derived> _Self>
- requires _MISSING_MEMBER(decay_t<_Self>, schedule) &&
- scheduler<__member_t<_Self, _Base>>
- friend auto tag_invoke(_Schedule, _Self&& __self) noexcept(
- noexcept(stdexec::schedule(
- __declval<__member_t<_Self, _Base>>())))
- -> schedule_result_t<_Self>
- {
- return stdexec::schedule(__c_cast<__t>((_Self &&) __self).base());
- }
-
- template <tag_category<forwarding_scheduler_query> _Tag,
- same_as<_Derived> _Self, class... _As>
- requires __callable<_Tag, const _Base&, _As...>
- friend auto
- tag_invoke(_Tag __tag, const _Self& __self, _As&&... __as) noexcept(
- __nothrow_callable<_Tag, const _Base&, _As...>)
- -> __call_result_if_t<
- tag_category<_Tag, forwarding_scheduler_query>, _Tag,
- const _Base&, _As...>
- {
- return ((_Tag &&) __tag)(__c_cast<__t>(__self).base(),
- (_As &&) __as...);
- }
-
- protected:
- using __adaptor_base<_Base>::base;
-
- public:
- __t() = default;
- using __adaptor_base<_Base>::__adaptor_base;
- };
-};
} // namespace __adaptors
-// NOT TO SPEC
-template <__class _Derived, sender _Base>
-using sender_adaptor =
- typename __adaptors::sender_adaptor<_Derived, _Base>::__t;
-
template <__class _Derived, receiver _Base = __adaptors::__not_a_receiver>
using receiver_adaptor =
typename __adaptors::receiver_adaptor<_Derived, _Base>::__t;
-// NOT TO SPEC
-template <__class _Derived, operation_state _Base>
-using operation_state_adaptor =
- typename __adaptors::operation_state_adaptor<_Derived, _Base>::__t;
-
-// NOT TO SPEC
-template <__class _Derived, scheduler _Base>
-using scheduler_adaptor =
- typename __adaptors::scheduler_adaptor<_Derived, _Base>::__t;
-
template <class _Receiver, class... _As>
concept __receiver_of_maybe_void =
(same_as<__types<void>, __types<_As...>> &&
@@ -2752,114 +2705,161 @@
using __non_throwing_ = __bool<__nothrow_invocable<_Fun, _Args...>>;
template <class _Tag, class _Fun, class _Sender, class _Env>
-using __with_error_invoke_t = __if_c<
- __v<__gather_sigs_t<_Tag, _Sender, _Env,
- __mbind_front_q<__non_throwing_, _Fun>, __q<__mand>>>,
- completion_signatures<>, __with_exception_ptr>;
+using __with_error_invoke_t =
+ __if_c<__v<__gather_completions_for<_Tag, _Sender, _Env,
+ __mbind_front_q<__non_throwing_, _Fun>,
+ __q<__mand>>>,
+ completion_signatures<>, __with_exception_ptr>;
template <class _Fun, class... _Args>
requires invocable<_Fun, _Args...>
using __set_value_invoke_t =
- completion_signatures<__minvoke1<__remove<void, __qf<set_value_t>>,
- std::invoke_result_t<_Fun, _Args...>>>;
+ completion_signatures<__minvoke<__remove<void, __qf<set_value_t>>,
+ std::invoke_result_t<_Fun, _Args...>>>;
/////////////////////////////////////////////////////////////////////////////
// [execution.senders.adaptors.then]
namespace __then
{
-template <class _ReceiverId, class _FunId>
-class __receiver :
- receiver_adaptor<__receiver<_ReceiverId, _FunId>, __t<_ReceiverId>>
+template <class _ReceiverId, class _Fun>
+struct __receiver
{
-#if STDEXEC_NON_LEXICAL_FRIENDSHIP
- public:
-#endif
using _Receiver = stdexec::__t<_ReceiverId>;
- using _Fun = stdexec::__t<_FunId>;
- friend receiver_adaptor<__receiver, _Receiver>;
- [[no_unique_address]] _Fun __f_;
-
- // Customize set_value by invoking the invocable and passing the result
- // to the base class
- template <class... _As>
- requires invocable<_Fun, _As...> &&
- __receiver_of_invoke_result<_Receiver, _Fun, _As...>
- void set_value(_As&&... __as) && noexcept
+ struct __data
{
- stdexec::__set_value_invoke(((__receiver &&) * this).base(),
- (_Fun &&) __f_, (_As &&) __as...);
- }
+ _Receiver __rcvr_;
+ [[no_unique_address]] _Fun __fun_;
+ };
- public:
- explicit __receiver(_Receiver __rcvr, _Fun __fun) :
- receiver_adaptor<__receiver, _Receiver>((_Receiver &&) __rcvr),
- __f_((_Fun &&) __fun)
- {}
+ struct __t
+ {
+ using __id = __receiver;
+ __data* __op_;
+
+ // Customize set_value by invoking the invocable and passing the result
+ // to the downstream receiver
+ template <__same_as<set_value_t> _Tag, class... _As>
+ requires invocable<_Fun, _As...> &&
+ __receiver_of_invoke_result<_Receiver, _Fun, _As...>
+ friend void tag_invoke(_Tag, __t&& __self, _As&&... __as) noexcept
+ {
+ stdexec::__set_value_invoke((_Receiver &&) __self.__op_->__rcvr_,
+ (_Fun &&) __self.__op_->__fun_,
+ (_As &&) __as...);
+ }
+
+ template <__one_of<set_error_t, set_stopped_t> _Tag, class... _As>
+ requires __callable<_Tag, _Receiver, _As...>
+ friend void tag_invoke(_Tag __tag, __t&& __self, _As&&... __as) noexcept
+ {
+ __tag((_Receiver &&) __self.__op_->__rcvr_, (_As &&) __as...);
+ }
+
+ friend auto tag_invoke(get_env_t, const __t& __self)
+ -> __call_result_t<get_env_t, const _Receiver&>
+ {
+ return get_env(__self.__op_->__rcvr_);
+ }
+ };
};
-template <class _SenderId, class _FunId>
+template <class _Sender, class _ReceiverId, class _Fun>
+struct __operation
+{
+ using _Receiver = stdexec::__t<_ReceiverId>;
+ using __receiver_id = __receiver<_ReceiverId, _Fun>;
+ using __receiver_t = stdexec::__t<__receiver_id>;
+ struct __t : __immovable
+ {
+ using __id = __operation;
+ typename __receiver_id::__data __data_;
+ connect_result_t<_Sender, __receiver_t> __op_;
+
+ __t(_Sender&& __sndr, _Receiver __rcvr, _Fun __fun) :
+ __data_{(_Receiver &&) __rcvr, (_Fun &&) __fun},
+ __op_(connect((_Sender &&) __sndr, __receiver_t{&__data_}))
+ {}
+
+ friend void tag_invoke(start_t, __t& __self) noexcept
+ {
+ start(__self.__op_);
+ }
+ };
+};
+
+template <class _SenderId, class _Fun>
struct __sender
{
- using _Sender = __t<_SenderId>;
- using _Fun = __t<_FunId>;
- template <receiver _Receiver>
- using __receiver = __receiver<__x<remove_cvref_t<_Receiver>>, _FunId>;
+ using _Sender = stdexec::__t<_SenderId>;
+ template <class _Receiver>
+ using __receiver = stdexec::__t<__receiver<stdexec::__id<_Receiver>, _Fun>>;
+ template <class _Self, class _Receiver>
+ using __operation =
+ stdexec::__t<__operation<__copy_cvref_t<_Self, _Sender>,
+ stdexec::__id<_Receiver>, _Fun>>;
- [[no_unique_address]] _Sender __sndr_;
- [[no_unique_address]] _Fun __fun_;
-
- template <class _Self, class _Env>
- using __completion_signatures = __make_completion_signatures<
- __member_t<_Self, _Sender>, _Env,
- __with_error_invoke_t<set_value_t, _Fun, __member_t<_Self, _Sender>,
- _Env>,
- __mbind_front_q<__set_value_invoke_t, _Fun>>;
-
- template <__decays_to<__sender> _Self, receiver _Receiver>
- // BUGBUG
- requires sender_to<__member_t<_Self, _Sender>, __receiver<_Receiver>>
- friend auto tag_invoke(connect_t, _Self&& __self, _Receiver&& __rcvr)
- // BUGBUG
- noexcept(__nothrow_connectable<__member_t<_Self, _Sender>,
- __receiver<_Receiver>>)
- // BUGBUG
- -> connect_result_t<__member_t<_Self, _Sender>, __receiver<_Receiver>>
+ struct __t
{
- return stdexec::connect(
- ((_Self &&) __self).__sndr_,
- __receiver<_Receiver>{(_Receiver &&) __rcvr,
- ((_Self &&) __self).__fun_});
- }
+ using __id = __sender;
+ [[no_unique_address]] _Sender __sndr_;
+ [[no_unique_address]] _Fun __fun_;
- template <__decays_to<__sender> _Self, class _Env>
- friend auto tag_invoke(get_completion_signatures_t, _Self&&, _Env)
- -> dependent_completion_signatures<_Env>;
+ template <class _Self, class _Env>
+ using __completion_signatures = __make_completion_signatures<
+ __copy_cvref_t<_Self, _Sender>, _Env,
+ __with_error_invoke_t<set_value_t, _Fun,
+ __copy_cvref_t<_Self, _Sender>, _Env>,
+ __mbind_front_q<__set_value_invoke_t, _Fun>>;
- template <__decays_to<__sender> _Self, class _Env>
- friend auto tag_invoke(get_completion_signatures_t, _Self&&, _Env)
- -> __completion_signatures<_Self, _Env>
- requires true;
+ template <__decays_to<__t> _Self, receiver _Receiver>
+ requires sender_to<__copy_cvref_t<_Self, _Sender>,
+ __receiver<_Receiver>>
+ friend auto tag_invoke(connect_t, _Self&& __self, _Receiver __rcvr)
+ -> __operation<_Self, _Receiver>
+ {
+ return {((_Self &&) __self).__sndr_, (_Receiver &&) __rcvr,
+ ((_Self &&) __self).__fun_};
+ }
- // forward sender queries:
- template <tag_category<forwarding_sender_query> _Tag, class... _As>
- requires __callable<_Tag, const _Sender&, _As...>
- friend auto
- tag_invoke(_Tag __tag, const __sender& __self, _As&&... __as) noexcept(
- __nothrow_callable<_Tag, const _Sender&, _As...>)
+ template <__decays_to<__t> _Self, class _Env>
+ friend auto tag_invoke(get_completion_signatures_t, _Self&&, _Env)
+ -> dependent_completion_signatures<_Env>;
+
+ template <__decays_to<__t> _Self, class _Env>
+ friend auto tag_invoke(get_completion_signatures_t, _Self&&, _Env)
+ -> __completion_signatures<_Self, _Env>
+ requires true;
+
+ // forward sender queries:
+ template <tag_category<forwarding_sender_query> _Tag, class... _As>
+ requires __callable<_Tag, const _Sender&, _As...>
+ friend auto tag_invoke(
+ _Tag __tag, const __t& __self,
+ _As&&... __as) noexcept(__nothrow_callable<_Tag, const _Sender&,
+ _As...>)
-> __call_result_if_t<tag_category<_Tag, forwarding_sender_query>,
_Tag, const _Sender&, _As...>
- {
- return ((_Tag &&) __tag)(__self.__sndr_, (_As &&) __as...);
- }
+ {
+ return ((_Tag &&) __tag)(__self.__sndr_, (_As &&) __as...);
+ }
+ };
};
struct then_t
{
template <class _Sender, class _Fun>
- using __sender =
- __sender<__x<remove_cvref_t<_Sender>>, __x<remove_cvref_t<_Fun>>>;
+ using __sender = __t<__sender<stdexec::__id<decay_t<_Sender>>, _Fun>>;
template <sender _Sender, __movable_value _Fun>
+ requires(!__tag_invocable_with_completion_scheduler<then_t, set_value_t,
+ _Sender, _Fun>) &&
+ (!tag_invocable<then_t, _Sender, _Fun>) &&
+ sender<__sender<_Sender, _Fun>>
+ __sender<_Sender, _Fun> operator()(_Sender&& __sndr, _Fun __fun) const
+ {
+ return __sender<_Sender, _Fun>{(_Sender &&) __sndr, (_Fun &&) __fun};
+ }
+ template <sender _Sender, __movable_value _Fun>
requires __tag_invocable_with_completion_scheduler<then_t, set_value_t,
_Sender, _Fun>
sender auto operator()(_Sender&& __sndr, _Fun __fun) const
@@ -2880,15 +2880,6 @@
{
return tag_invoke(then_t{}, (_Sender &&) __sndr, (_Fun &&) __fun);
}
- template <sender _Sender, __movable_value _Fun>
- requires(!__tag_invocable_with_completion_scheduler<then_t, set_value_t,
- _Sender, _Fun>) &&
- (!tag_invocable<then_t, _Sender, _Fun>) &&
- sender<__sender<_Sender, _Fun>>
- __sender<_Sender, _Fun> operator()(_Sender&& __sndr, _Fun __fun) const
- {
- return __sender<_Sender, _Fun>{(_Sender &&) __sndr, (_Fun &&) __fun};
- }
template <class _Fun>
__binder_back<then_t, _Fun> operator()(_Fun __fun) const
{
@@ -2903,92 +2894,103 @@
// [execution.senders.adaptors.upon_error]
namespace __upon_error
{
-template <class _ReceiverId, class _FunId>
-class __receiver :
- receiver_adaptor<__receiver<_ReceiverId, _FunId>, __t<_ReceiverId>>
+template <class _ReceiverId, class _Fun>
+struct __receiver
{
using _Receiver = stdexec::__t<_ReceiverId>;
- using _Fun = stdexec::__t<_FunId>;
- friend receiver_adaptor<__receiver, _Receiver>;
- [[no_unique_address]] _Fun __f_;
- // Customize set_error by invoking the invocable and passing the result
- // to the base class
- template <class _Error>
- requires invocable<_Fun, _Error> &&
- __receiver_of_invoke_result<_Receiver, _Fun, _Error>
- void set_error(_Error&& __err) && noexcept
+ class __t : receiver_adaptor<__t, _Receiver>
{
- stdexec::__set_value_invoke(((__receiver &&) * this).base(),
- (_Fun &&) __f_, (_Error &&) __err);
- }
+ friend receiver_adaptor<__t, _Receiver>;
+ [[no_unique_address]] _Fun __f_;
- public:
- explicit __receiver(_Receiver __rcvr, _Fun __fun) :
- receiver_adaptor<__receiver, _Receiver>((_Receiver &&) __rcvr),
- __f_((_Fun &&) __fun)
- {}
+ // Customize set_error by invoking the invocable and passing the result
+ // to the base class
+ template <class _Error>
+ requires invocable<_Fun, _Error> &&
+ __receiver_of_invoke_result<_Receiver, _Fun, _Error>
+ void set_error(_Error&& __err) && noexcept
+ {
+ stdexec::__set_value_invoke(((__t &&) * this).base(),
+ (_Fun &&) __f_, (_Error &&) __err);
+ }
+
+ public:
+ using __id = __receiver;
+
+ explicit __t(_Receiver __rcvr, _Fun __fun) :
+ receiver_adaptor<__t, _Receiver>((_Receiver &&) __rcvr),
+ __f_((_Fun &&) __fun)
+ {}
+ };
};
-template <class _SenderId, class _FunId>
+template <class _SenderId, class _Fun>
struct __sender
{
- using _Sender = __t<_SenderId>;
- using _Fun = __t<_FunId>;
+ using _Sender = stdexec::__t<_SenderId>;
+
template <class _Receiver>
- using __receiver = __receiver<__x<remove_cvref_t<_Receiver>>, _FunId>;
+ using __receiver = stdexec::__t<__receiver<stdexec::__id<_Receiver>, _Fun>>;
- [[no_unique_address]] _Sender __sndr_;
- [[no_unique_address]] _Fun __fun_;
-
- template <class _Self, class _Env>
- using __completion_signatures = __make_completion_signatures<
- __member_t<_Self, _Sender>, _Env,
- __with_error_invoke_t<set_error_t, _Fun, __member_t<_Self, _Sender>,
- _Env>,
- __q<__compl_sigs::__default_set_value>,
- __mbind_front_q<__set_value_invoke_t, _Fun>>;
-
- template <__decays_to<__sender> _Self, receiver _Receiver>
- requires sender_to<__member_t<_Self, _Sender>, __receiver<_Receiver>>
- friend auto tag_invoke(
- connect_t, _Self&& __self,
- _Receiver&&
- __rcvr) noexcept(__nothrow_connectable<__member_t<_Self, _Sender>,
- __receiver<_Receiver>>)
- -> connect_result_t<__member_t<_Self, _Sender>, __receiver<_Receiver>>
+ struct __t
{
- return stdexec::connect(
- ((_Self &&) __self).__sndr_,
- __receiver<_Receiver>{(_Receiver &&) __rcvr,
- ((_Self &&) __self).__fun_});
- }
+ using __id = __sender;
- template <__decays_to<__sender> _Self, class _Env>
- friend auto tag_invoke(get_completion_signatures_t, _Self&&, _Env)
- -> dependent_completion_signatures<_Env>;
- template <__decays_to<__sender> _Self, class _Env>
- friend auto tag_invoke(get_completion_signatures_t, _Self&&, _Env)
- -> __completion_signatures<_Self, _Env>
- requires true;
+ [[no_unique_address]] _Sender __sndr_;
+ [[no_unique_address]] _Fun __fun_;
- template <tag_category<forwarding_sender_query> _Tag, class _Error>
- requires __callable<_Tag, const _Sender&, _Error>
- friend auto
- tag_invoke(_Tag __tag, const __sender& __self, _Error&& __err) noexcept(
- __nothrow_callable<_Tag, const _Sender&, _Error>)
+ template <class _Self, class _Env>
+ using __completion_signatures = __make_completion_signatures<
+ __copy_cvref_t<_Self, _Sender>, _Env,
+ __with_error_invoke_t<set_error_t, _Fun,
+ __copy_cvref_t<_Self, _Sender>, _Env>,
+ __q<__compl_sigs::__default_set_value>,
+ __mbind_front_q<__set_value_invoke_t, _Fun>>;
+
+ template <__decays_to<__t> _Self, receiver _Receiver>
+ requires sender_to<__copy_cvref_t<_Self, _Sender>,
+ __receiver<_Receiver>>
+ friend auto
+ tag_invoke(connect_t, _Self&& __self, _Receiver __rcvr) noexcept(
+ __nothrow_connectable<__copy_cvref_t<_Self, _Sender>,
+ __receiver<_Receiver>>)
+ -> connect_result_t<__copy_cvref_t<_Self, _Sender>,
+ __receiver<_Receiver>>
+ {
+ return stdexec::connect(
+ ((_Self &&) __self).__sndr_,
+ __receiver<_Receiver>{(_Receiver &&) __rcvr,
+ ((_Self &&) __self).__fun_});
+ }
+
+ template <__decays_to<__t> _Self, class _Env>
+ friend auto tag_invoke(get_completion_signatures_t, _Self&&, _Env)
+ -> dependent_completion_signatures<_Env>;
+ template <__decays_to<__t> _Self, class _Env>
+ friend auto tag_invoke(get_completion_signatures_t, _Self&&, _Env)
+ -> __completion_signatures<_Self, _Env>
+ requires true;
+
+ template <tag_category<forwarding_sender_query> _Tag, class _Error>
+ requires __callable<_Tag, const _Sender&, _Error>
+ friend auto tag_invoke(
+ _Tag __tag, const __t& __self,
+ _Error&& __err) noexcept(__nothrow_callable<_Tag, const _Sender&,
+ _Error>)
-> __call_result_if_t<tag_category<_Tag, forwarding_sender_query>,
_Tag, const _Sender&, _Error>
- {
- return ((_Tag &&) __tag)(__self.__sndr_, (_Error &&) __err);
- }
+ {
+ return ((_Tag &&) __tag)(__self.__sndr_, (_Error &&) __err);
+ }
+ };
};
struct upon_error_t
{
template <class _Sender, class _Fun>
using __sender =
- __sender<__x<remove_cvref_t<_Sender>>, __x<remove_cvref_t<_Fun>>>;
+ __t<__sender<stdexec::__id<remove_cvref_t<_Sender>>, _Fun>>;
template <sender _Sender, __movable_value _Fun>
requires __tag_invocable_with_completion_scheduler<
@@ -3034,91 +3036,100 @@
// [execution.senders.adaptors.upon_stopped]
namespace __upon_stopped
{
-template <class _ReceiverId, class _FunId>
-class __receiver :
- receiver_adaptor<__receiver<_ReceiverId, _FunId>, __t<_ReceiverId>>
+template <class _ReceiverId, class _Fun>
+struct __receiver
{
using _Receiver = stdexec::__t<_ReceiverId>;
- using _Fun = stdexec::__t<_FunId>;
- friend receiver_adaptor<__receiver, _Receiver>;
- [[no_unique_address]] _Fun __f_;
- // Customize set_stopped by invoking the invocable and passing the result
- // to the base class
- void set_stopped() && noexcept
+ class __t : receiver_adaptor<__t, _Receiver>
{
- stdexec::__set_value_invoke(((__receiver &&) * this).base(),
- (_Fun &&) __f_);
- }
+ friend receiver_adaptor<__t, _Receiver>;
+ [[no_unique_address]] _Fun __f_;
- public:
- explicit __receiver(_Receiver __rcvr, _Fun __fun) :
- receiver_adaptor<__receiver, _Receiver>((_Receiver &&) __rcvr),
- __f_((_Fun &&) __fun)
- {}
+ // Customize set_stopped by invoking the invocable and passing the
+ // result to the base class
+ void set_stopped() && noexcept
+ {
+ stdexec::__set_value_invoke(((__t &&) * this).base(),
+ (_Fun &&) __f_);
+ }
+
+ public:
+ using __id = __receiver;
+ explicit __t(_Receiver __rcvr, _Fun __fun) :
+ receiver_adaptor<__t, _Receiver>((_Receiver &&) __rcvr),
+ __f_((_Fun &&) __fun)
+ {}
+ };
};
-template <class _SenderId, class _FunId>
+template <class _SenderId, class _Fun>
struct __sender
{
- using _Sender = __t<_SenderId>;
- using _Fun = __t<_FunId>;
+ using _Sender = stdexec::__t<_SenderId>;
+
template <class _Receiver>
- using __receiver = __receiver<__x<remove_cvref_t<_Receiver>>, _FunId>;
+ using __receiver = stdexec::__t<__receiver<stdexec::__id<_Receiver>, _Fun>>;
- [[no_unique_address]] _Sender __sndr_;
- [[no_unique_address]] _Fun __fun_;
-
- template <class _Self, class _Env>
- using __completion_signatures = __make_completion_signatures<
- __member_t<_Self, _Sender>, _Env,
- __with_error_invoke_t<set_stopped_t, _Fun, __member_t<_Self, _Sender>,
- _Env>,
- __q<__compl_sigs::__default_set_value>,
- __q1<__compl_sigs::__default_set_error>, __set_value_invoke_t<_Fun>>;
-
- template <__decays_to<__sender> _Self, receiver _Receiver>
- requires __receiver_of_invoke_result<_Receiver, _Fun> &&
- sender_to<__member_t<_Self, _Sender>, __receiver<_Receiver>>
- friend auto tag_invoke(
- connect_t, _Self&& __self,
- _Receiver&&
- __rcvr) noexcept(__nothrow_connectable<_Sender,
- __receiver<
- _Receiver>>)
- -> connect_result_t<__member_t<_Self, _Sender>,
- __receiver<_Receiver>>
+ struct __t
{
- return stdexec::connect(
- ((_Self &&) __self).__sndr_,
- __receiver<_Receiver>{(_Receiver &&) __rcvr,
- ((_Self &&) __self).__fun_});
- }
+ using __id = __sender;
- template <__decays_to<__sender> _Self, class _Env>
- friend auto tag_invoke(get_completion_signatures_t, _Self&&, _Env)
- -> dependent_completion_signatures<_Env>;
- template <__decays_to<__sender> _Self, class _Env>
- friend auto tag_invoke(get_completion_signatures_t, _Self&&, _Env)
- -> __completion_signatures<_Self, _Env>
- requires true;
+ [[no_unique_address]] _Sender __sndr_;
+ [[no_unique_address]] _Fun __fun_;
- template <tag_category<forwarding_sender_query> _Tag>
- requires __callable<_Tag, const _Sender&>
- friend auto tag_invoke(_Tag __tag, const __sender& __self) noexcept(
- __nothrow_callable<_Tag, const _Sender&>)
- -> __call_result_if_t<tag_category<_Tag, forwarding_sender_query>, _Tag,
- const _Sender&>
- {
- return ((_Tag &&) __tag)(__self.__sndr_);
- }
+ template <class _Self, class _Env>
+ using __completion_signatures = __make_completion_signatures<
+ __copy_cvref_t<_Self, _Sender>, _Env,
+ __with_error_invoke_t<set_stopped_t, _Fun,
+ __copy_cvref_t<_Self, _Sender>, _Env>,
+ __q<__compl_sigs::__default_set_value>,
+ __q<__compl_sigs::__default_set_error>, __set_value_invoke_t<_Fun>>;
+
+ template <__decays_to<__t> _Self, receiver _Receiver>
+ requires __receiver_of_invoke_result<_Receiver, _Fun> &&
+ sender_to<__copy_cvref_t<_Self, _Sender>,
+ __receiver<_Receiver>>
+ friend auto tag_invoke(
+ connect_t, _Self&& __self,
+ _Receiver
+ __rcvr) noexcept(__nothrow_connectable<_Sender,
+ __receiver<
+ _Receiver>>)
+ -> connect_result_t<__copy_cvref_t<_Self, _Sender>,
+ __receiver<_Receiver>>
+ {
+ return stdexec::connect(
+ ((_Self &&) __self).__sndr_,
+ __receiver<_Receiver>{(_Receiver &&) __rcvr,
+ ((_Self &&) __self).__fun_});
+ }
+
+ template <__decays_to<__t> _Self, class _Env>
+ friend auto tag_invoke(get_completion_signatures_t, _Self&&, _Env)
+ -> dependent_completion_signatures<_Env>;
+ template <__decays_to<__t> _Self, class _Env>
+ friend auto tag_invoke(get_completion_signatures_t, _Self&&, _Env)
+ -> __completion_signatures<_Self, _Env>
+ requires true;
+
+ template <tag_category<forwarding_sender_query> _Tag>
+ requires __callable<_Tag, const _Sender&>
+ friend auto tag_invoke(_Tag __tag, const __t& __self) noexcept(
+ __nothrow_callable<_Tag, const _Sender&>)
+ -> __call_result_if_t<tag_category<_Tag, forwarding_sender_query>,
+ _Tag, const _Sender&>
+ {
+ return ((_Tag &&) __tag)(__self.__sndr_);
+ }
+ };
};
struct upon_stopped_t
{
template <class _Sender, class _Fun>
using __sender =
- __sender<__x<remove_cvref_t<_Sender>>, __x<remove_cvref_t<_Fun>>>;
+ __t<__sender<stdexec::__id<remove_cvref_t<_Sender>>, _Fun>>;
template <sender _Sender, __movable_value _Fun>
requires __tag_invocable_with_completion_scheduler<
@@ -3166,33 +3177,21 @@
// [execution.senders.adaptors.bulk]
namespace __bulk
{
-template <class _ReceiverId, integral _Shape, class _FunId>
-class __receiver :
- receiver_adaptor<__receiver<_ReceiverId, _Shape, _FunId>, __t<_ReceiverId>>
+template <class _ReceiverId, integral _Shape, class _Fun>
+struct __receiver
{
using _Receiver = stdexec::__t<_ReceiverId>;
- using _Fun = stdexec::__t<_FunId>;
- friend receiver_adaptor<__receiver, _Receiver>;
- [[no_unique_address]] _Shape __shape_;
- [[no_unique_address]] _Fun __f_;
-
- template <class... _As>
- void set_value(_As&&... __as) && noexcept
- requires __nothrow_callable<_Fun, _Shape, _As&...>
+ class __t : receiver_adaptor<__t, _Receiver>
{
- for (_Shape __i{}; __i != __shape_; ++__i)
- {
- __f_(__i, __as...);
- }
- stdexec::set_value(std::move(this->base()), (_As &&) __as...);
- }
+ friend receiver_adaptor<__t, _Receiver>;
- template <class... _As>
- void set_value(_As&&... __as) && noexcept
- requires __callable<_Fun, _Shape, _As&...>
- {
- try
+ [[no_unique_address]] _Shape __shape_;
+ [[no_unique_address]] _Fun __f_;
+
+ template <class... _As>
+ void set_value(_As&&... __as) && noexcept
+ requires __nothrow_callable<_Fun, _Shape, _As&...>
{
for (_Shape __i{}; __i != __shape_; ++__i)
{
@@ -3200,86 +3199,108 @@
}
stdexec::set_value(std::move(this->base()), (_As &&) __as...);
}
- catch (...)
- {
- stdexec::set_error(std::move(this->base()),
- std::current_exception());
- }
- }
- public:
- explicit __receiver(_Receiver __rcvr, _Shape __shape, _Fun __fun) :
- receiver_adaptor<__receiver, _Receiver>((_Receiver &&) __rcvr),
- __shape_(__shape), __f_((_Fun &&) __fun)
- {}
+ template <class... _As>
+ void set_value(_As&&... __as) && noexcept
+ requires __callable<_Fun, _Shape, _As&...>
+ {
+ try
+ {
+ for (_Shape __i{}; __i != __shape_; ++__i)
+ {
+ __f_(__i, __as...);
+ }
+ stdexec::set_value(std::move(this->base()), (_As &&) __as...);
+ }
+ catch (...)
+ {
+ stdexec::set_error(std::move(this->base()),
+ std::current_exception());
+ }
+ }
+
+ public:
+ using __id = __receiver;
+ explicit __t(_Receiver __rcvr, _Shape __shape, _Fun __fun) :
+ receiver_adaptor<__t, _Receiver>((_Receiver &&) __rcvr),
+ __shape_(__shape), __f_((_Fun &&) __fun)
+ {}
+ };
};
-template <class _SenderId, integral _Shape, class _FunId>
+template <class _SenderId, integral _Shape, class _Fun>
struct __sender
{
- using _Sender = __t<_SenderId>;
- using _Fun = __t<_FunId>;
+ using _Sender = stdexec::__t<_SenderId>;
+
template <receiver _Receiver>
using __receiver =
- __receiver<__x<remove_cvref_t<_Receiver>>, _Shape, _FunId>;
+ stdexec::__t<__receiver<stdexec::__id<_Receiver>, _Shape, _Fun>>;
- [[no_unique_address]] _Sender __sndr_;
- [[no_unique_address]] _Shape __shape_;
- [[no_unique_address]] _Fun __fun_;
-
- template <class _Fun, class _Sender, class _Env>
- using __with_error_invoke_t = __if_c<
- __v<__value_types_of_t<_Sender, _Env,
- __mbind_front_q<__non_throwing_, _Fun, _Shape>,
- __q<__mand>>>,
- completion_signatures<>, __with_exception_ptr>;
-
- template <class _Self, class _Env>
- using __completion_signatures = __make_completion_signatures<
- __member_t<_Self, _Sender>, _Env,
- __with_error_invoke_t<_Fun, __member_t<_Self, _Sender>, _Env>>;
-
- template <__decays_to<__sender> _Self, receiver _Receiver>
- requires sender_to<__member_t<_Self, _Sender>, __receiver<_Receiver>>
- friend auto tag_invoke(
- connect_t, _Self&& __self,
- _Receiver&&
- __rcvr) noexcept(__nothrow_connectable<__member_t<_Self, _Sender>,
- __receiver<_Receiver>>)
- -> connect_result_t<__member_t<_Self, _Sender>, __receiver<_Receiver>>
+ struct __t
{
- return stdexec::connect(
- ((_Self &&) __self).__sndr_,
- __receiver<_Receiver>{(_Receiver &&) __rcvr, __self.__shape_,
- ((_Self &&) __self).__fun_});
- }
+ using __id = __sender;
- template <__decays_to<__sender> _Self, class _Env>
- friend auto tag_invoke(get_completion_signatures_t, _Self&&, _Env)
- -> dependent_completion_signatures<_Env>;
+ [[no_unique_address]] _Sender __sndr_;
+ [[no_unique_address]] _Shape __shape_;
+ [[no_unique_address]] _Fun __fun_;
- template <__decays_to<__sender> _Self, class _Env>
- friend auto tag_invoke(get_completion_signatures_t, _Self&&, _Env)
- -> __completion_signatures<_Self, _Env>
- requires true;
+ template <class _Sender, class _Env>
+ using __with_error_invoke_t = __if_c<
+ __v<__value_types_of_t<
+ _Sender, _Env, __mbind_front_q<__non_throwing_, _Fun, _Shape>,
+ __q<__mand>>>,
+ completion_signatures<>, __with_exception_ptr>;
- template <tag_category<forwarding_sender_query> _Tag, class... _As>
- requires __callable<_Tag, const _Sender&, _As...>
- friend auto
- tag_invoke(_Tag __tag, const __sender& __self, _As&&... __as) noexcept(
- __nothrow_callable<_Tag, const _Sender&, _As...>)
+ template <class _Self, class _Env>
+ using __completion_signatures = __make_completion_signatures<
+ __copy_cvref_t<_Self, _Sender>, _Env,
+ __with_error_invoke_t<__copy_cvref_t<_Self, _Sender>, _Env>>;
+
+ template <__decays_to<__t> _Self, receiver _Receiver>
+ requires sender_to<__copy_cvref_t<_Self, _Sender>,
+ __receiver<_Receiver>>
+ friend auto
+ tag_invoke(connect_t, _Self&& __self, _Receiver __rcvr) noexcept(
+ __nothrow_connectable<__copy_cvref_t<_Self, _Sender>,
+ __receiver<_Receiver>>)
+ -> connect_result_t<__copy_cvref_t<_Self, _Sender>,
+ __receiver<_Receiver>>
+ {
+ return stdexec::connect(
+ ((_Self &&) __self).__sndr_,
+ __receiver<_Receiver>{(_Receiver &&) __rcvr, __self.__shape_,
+ ((_Self &&) __self).__fun_});
+ }
+
+ template <__decays_to<__t> _Self, class _Env>
+ friend auto tag_invoke(get_completion_signatures_t, _Self&&, _Env)
+ -> dependent_completion_signatures<_Env>;
+
+ template <__decays_to<__t> _Self, class _Env>
+ friend auto tag_invoke(get_completion_signatures_t, _Self&&, _Env)
+ -> __completion_signatures<_Self, _Env>
+ requires true;
+
+ template <tag_category<forwarding_sender_query> _Tag, class... _As>
+ requires __callable<_Tag, const _Sender&, _As...>
+ friend auto tag_invoke(
+ _Tag __tag, const __t& __self,
+ _As&&... __as) noexcept(__nothrow_callable<_Tag, const _Sender&,
+ _As...>)
-> __call_result_if_t<tag_category<_Tag, forwarding_sender_query>,
_Tag, const _Sender&, _As...>
- {
- return ((_Tag &&) __tag)(__self.__sndr_, (_As &&) __as...);
- }
+ {
+ return ((_Tag &&) __tag)(__self.__sndr_, (_As &&) __as...);
+ }
+ };
};
struct bulk_t
{
template <sender _Sender, integral _Shape, class _Fun>
- using __sender = __sender<__x<remove_cvref_t<_Sender>>, _Shape,
- __x<remove_cvref_t<_Fun>>>;
+ using __sender =
+ __t<__sender<stdexec::__id<remove_cvref_t<_Sender>>, _Shape, _Fun>>;
template <sender _Sender, integral _Shape, __movable_value _Fun>
requires __tag_invocable_with_completion_scheduler<
@@ -3330,50 +3351,58 @@
{
template <class _BaseEnv>
using __env_t = __make_env_t<_BaseEnv, // BUGBUG NOT TO SPEC
- __with_t<get_stop_token_t, in_place_stop_token>>;
+ __with<get_stop_token_t, in_place_stop_token>>;
template <class _SenderId, class _EnvId>
struct __sh_state;
template <class _SenderId, class _EnvId>
-class __receiver
+struct __receiver
{
- using _Sender = __t<_SenderId>;
- using _Env = __t<_EnvId>;
- __sh_state<_SenderId, _EnvId>& __sh_state_;
+ using _Sender = stdexec::__t<_SenderId>;
+ using _Env = stdexec::__t<_EnvId>;
- public:
- template <__one_of<set_value_t, set_error_t, set_stopped_t> _Tag,
- class... _As>
- friend void tag_invoke(_Tag __tag, __receiver&& __self,
- _As&&... __as) noexcept
+ class __t
{
- __sh_state<_SenderId, _EnvId>& __state = __self.__sh_state_;
+ stdexec::__t<__sh_state<_SenderId, _EnvId>>& __sh_state_;
- try
+ public:
+ using __id = __receiver;
+
+ template <__one_of<set_value_t, set_error_t, set_stopped_t> _Tag,
+ class... _As>
+ friend void tag_invoke(_Tag __tag, __t&& __self, _As&&... __as) noexcept
{
- using __tuple_t = __decayed_tuple<_Tag, _As...>;
- __state.__data_.template emplace<__tuple_t>(__tag,
- (_As &&) __as...);
+ stdexec::__t<__sh_state<_SenderId, _EnvId>>& __state =
+ __self.__sh_state_;
+
+ try
+ {
+ using __tuple_t = __decayed_tuple<_Tag, _As...>;
+ __state.__data_.template emplace<__tuple_t>(__tag,
+ (_As &&) __as...);
+ }
+ catch (...)
+ {
+ using __tuple_t =
+ __decayed_tuple<set_error_t, std::exception_ptr>;
+ __state.__data_.template emplace<__tuple_t>(
+ set_error, std::current_exception());
+ }
+ __state.__notify();
}
- catch (...)
+
+ friend const __env_t<_Env>& tag_invoke(get_env_t,
+ const __t& __self) noexcept
{
- using __tuple_t = __decayed_tuple<set_error_t, std::exception_ptr>;
- __state.__data_.template emplace<__tuple_t>(
- set_error, std::current_exception());
+ return __self.__sh_state_.__env_;
}
- __state.__notify();
- }
- friend const __env_t<_Env>& tag_invoke(get_env_t,
- const __receiver& __self) noexcept
- {
- return __self.__sh_state_.__env_;
- }
-
- explicit __receiver(__sh_state<_SenderId, _EnvId>& __sh_state) noexcept :
- __sh_state_(__sh_state)
- {}
+ explicit __t(
+ stdexec::__t<__sh_state<_SenderId, _EnvId>>& __sh_state) noexcept :
+ __sh_state_(__sh_state)
+ {}
+ };
};
struct __operation_base
@@ -3387,223 +3416,245 @@
template <class _SenderId, class _EnvId>
struct __sh_state
{
- using _Sender = __t<_SenderId>;
- using _Env = __t<_EnvId>;
+ using _Sender = stdexec::__t<_SenderId>;
+ using _Env = stdexec::__t<_EnvId>;
- template <class... _Ts>
- using __bind_tuples =
- __mbind_front_q<__variant,
- std::tuple<set_stopped_t>, // Initial state of the
- // variant is set_stopped
- std::tuple<set_error_t, std::exception_ptr>, _Ts...>;
-
- using __bound_values_t =
- __value_types_of_t<_Sender, __env_t<_Env>,
- __mbind_front_q<__decayed_tuple, set_value_t>,
- __q<__bind_tuples>>;
-
- using __variant_t = __error_types_of_t<
- _Sender, __env_t<_Env>,
- __transform<__mbind_front_q<__decayed_tuple, set_error_t>,
- __bound_values_t>>;
-
- using __receiver_ = __receiver<_SenderId, _EnvId>;
-
- in_place_stop_source __stop_source_{};
- __variant_t __data_;
- std::atomic<void*> __head_{nullptr};
- __env_t<_Env> __env_;
- connect_result_t<_Sender&, __receiver_> __op_state2_;
-
- explicit __sh_state(_Sender& __sndr, _Env __env) :
- __env_(__make_env((_Env &&) __env,
- __with(get_stop_token, __stop_source_.get_token()))),
- __op_state2_(connect(__sndr, __receiver_{*this}))
- {}
-
- void __notify() noexcept
+ struct __t
{
- void* const __completion_state = static_cast<void*>(this);
- void* __old = __head_.exchange(__completion_state,
- std::memory_order_acq_rel);
- __operation_base* __op_state = static_cast<__operation_base*>(__old);
+ using __id = __sh_state;
- while (__op_state != nullptr)
+ template <class... _Ts>
+ using __bind_tuples =
+ __mbind_front_q<__variant,
+ std::tuple<set_stopped_t>, // Initial state of the
+ // variant is set_stopped
+ std::tuple<set_error_t, std::exception_ptr>,
+ _Ts...>;
+
+ using __bound_values_t =
+ __value_types_of_t<_Sender, __env_t<_Env>,
+ __mbind_front_q<__decayed_tuple, set_value_t>,
+ __q<__bind_tuples>>;
+
+ using __variant_t = __error_types_of_t<
+ _Sender, __env_t<_Env>,
+ __transform<__mbind_front_q<__decayed_tuple, set_error_t>,
+ __bound_values_t>>;
+
+ using __receiver_ = stdexec::__t<__receiver<_SenderId, _EnvId>>;
+
+ in_place_stop_source __stop_source_{};
+ __variant_t __data_;
+ std::atomic<void*> __head_{nullptr};
+ __env_t<_Env> __env_;
+ connect_result_t<_Sender&, __receiver_> __op_state2_;
+
+ explicit __t(_Sender& __sndr, _Env __env) :
+ __env_(__make_env(
+ (_Env &&) __env,
+ __with_(get_stop_token, __stop_source_.get_token()))),
+ __op_state2_(connect(__sndr, __receiver_{*this}))
+ {}
+
+ void __notify() noexcept
{
- __operation_base* __next = __op_state->__next_;
- __op_state->__notify_(__op_state);
- __op_state = __next;
+ void* const __completion_state = static_cast<void*>(this);
+ void* __old = __head_.exchange(__completion_state,
+ std::memory_order_acq_rel);
+ __operation_base* __op_state =
+ static_cast<__operation_base*>(__old);
+
+ while (__op_state != nullptr)
+ {
+ __operation_base* __next = __op_state->__next_;
+ __op_state->__notify_(__op_state);
+ __op_state = __next;
+ }
}
- }
+ };
};
template <class _SenderId, class _EnvId, class _ReceiverId>
-class __operation : public __operation_base
+struct __operation
{
- using _Sender = __t<_SenderId>;
- using _Env = __t<_EnvId>;
- using _Receiver = __t<_ReceiverId>;
+ using _Sender = stdexec::__t<_SenderId>;
+ using _Env = stdexec::__t<_EnvId>;
+ using _Receiver = stdexec::__t<_ReceiverId>;
- struct __on_stop_requested
+ class __t : public __operation_base
{
- in_place_stop_source& __stop_source_;
- void operator()() noexcept
+ struct __on_stop_requested
{
- __stop_source_.request_stop();
+ in_place_stop_source& __stop_source_;
+ void operator()() noexcept
+ {
+ __stop_source_.request_stop();
+ }
+ };
+ using __on_stop = std::optional<typename stop_token_of_t<
+ env_of_t<_Receiver>&>::template callback_type<__on_stop_requested>>;
+
+ _Receiver __recvr_;
+ __on_stop __on_stop_{};
+ std::shared_ptr<stdexec::__t<__sh_state<_SenderId, _EnvId>>>
+ __shared_state_;
+
+ public:
+ using __id = __operation;
+ __t(_Receiver&& __rcvr,
+ std::shared_ptr<stdexec::__t<__sh_state<_SenderId, _EnvId>>>
+ __shared_state) noexcept(std::
+ is_nothrow_move_constructible_v<
+ _Receiver>) :
+ __operation_base{nullptr, __notify},
+ __recvr_((_Receiver &&) __rcvr),
+ __shared_state_(std::move(__shared_state))
+ {}
+ STDEXEC_IMMOVABLE(__t);
+
+ static void __notify(__operation_base* __self) noexcept
+ {
+ __t* __op = static_cast<__t*>(__self);
+ __op->__on_stop_.reset();
+
+ std::visit(
+ [&](const auto& __tupl) noexcept -> void {
+ std::apply(
+ [&](auto __tag,
+ const auto&... __args) noexcept -> void {
+ __tag((_Receiver &&) __op->__recvr_, __args...);
+ },
+ __tupl);
+ },
+ __op->__shared_state_->__data_);
+ }
+
+ friend void tag_invoke(start_t, __t& __self) noexcept
+ {
+ stdexec::__t<__sh_state<_SenderId, _EnvId>>* __shared_state =
+ __self.__shared_state_.get();
+ std::atomic<void*>& __head = __shared_state->__head_;
+ void* const __completion_state = static_cast<void*>(__shared_state);
+ void* __old = __head.load(std::memory_order_acquire);
+
+ if (__old != __completion_state)
+ {
+ __self.__on_stop_.emplace(
+ get_stop_token(get_env(__self.__recvr_)),
+ __on_stop_requested{__shared_state->__stop_source_});
+ }
+
+ do
+ {
+ if (__old == __completion_state)
+ {
+ __self.__notify(&__self);
+ return;
+ }
+ __self.__next_ = static_cast<__operation_base*>(__old);
+ } while (!__head.compare_exchange_weak(
+ __old, static_cast<void*>(&__self), std::memory_order_release,
+ std::memory_order_acquire));
+
+ if (__old == nullptr)
+ {
+ // the inner sender isn't running
+ if (__shared_state->__stop_source_.stop_requested())
+ {
+ // 1. resets __head to completion state
+ // 2. notifies waiting threads
+ // 3. propagates "stopped" signal to `out_r'`
+ __shared_state->__notify();
+ }
+ else
+ {
+ start(__shared_state->__op_state2_);
+ }
+ }
}
};
- using __on_stop = std::optional<typename stop_token_of_t<
- env_of_t<_Receiver>&>::template callback_type<__on_stop_requested>>;
-
- _Receiver __recvr_;
- __on_stop __on_stop_{};
- std::shared_ptr<__sh_state<_SenderId, _EnvId>> __shared_state_;
-
- public:
- __operation(
- _Receiver&& __rcvr,
- std::shared_ptr<__sh_state<_SenderId, _EnvId>>
- __shared_state) noexcept(std::
- is_nothrow_move_constructible_v<
- _Receiver>) :
- __operation_base{nullptr, __notify},
- __recvr_((_Receiver &&) __rcvr),
- __shared_state_(std::move(__shared_state))
- {}
- STDEXEC_IMMOVABLE(__operation);
-
- static void __notify(__operation_base* __self) noexcept
- {
- __operation* __op = static_cast<__operation*>(__self);
- __op->__on_stop_.reset();
-
- std::visit(
- [&](const auto& __tupl) noexcept -> void {
- std::apply(
- [&](auto __tag, const auto&... __args) noexcept -> void {
- __tag((_Receiver &&) __op->__recvr_, __args...);
- },
- __tupl);
- },
- __op->__shared_state_->__data_);
- }
-
- friend void tag_invoke(start_t, __operation& __self) noexcept
- {
- __sh_state<_SenderId, _EnvId>* __shared_state =
- __self.__shared_state_.get();
- std::atomic<void*>& __head = __shared_state->__head_;
- void* const __completion_state = static_cast<void*>(__shared_state);
- void* __old = __head.load(std::memory_order_acquire);
-
- if (__old != __completion_state)
- {
- __self.__on_stop_.emplace(
- get_stop_token(get_env(__self.__recvr_)),
- __on_stop_requested{__shared_state->__stop_source_});
- }
-
- do
- {
- if (__old == __completion_state)
- {
- __self.__notify(&__self);
- return;
- }
- __self.__next_ = static_cast<__operation_base*>(__old);
- } while (!__head.compare_exchange_weak(
- __old, static_cast<void*>(&__self), std::memory_order_release,
- std::memory_order_acquire));
-
- if (__old == nullptr)
- {
- // the inner sender isn't running
- if (__shared_state->__stop_source_.stop_requested())
- {
- // 1. resets __head to completion state
- // 2. notifies waiting threads
- // 3. propagates "stopped" signal to `out_r'`
- __shared_state->__notify();
- }
- else
- {
- start(__shared_state->__op_state2_);
- }
- }
- }
};
template <class _SenderId, class _EnvId>
-class __sender
+struct __sender
{
- using _Sender = __t<_SenderId>;
- using _Env = __t<_EnvId>;
- using __sh_state_ = __sh_state<_SenderId, _EnvId>;
+ using _Sender = stdexec::__t<_SenderId>;
+ using _Env = stdexec::__t<_EnvId>;
+
template <class _Receiver>
using __operation =
- __operation<_SenderId, _EnvId, __x<remove_cvref_t<_Receiver>>>;
+ stdexec::__t<__operation<_SenderId, _EnvId, stdexec::__id<_Receiver>>>;
- template <class... _Tys>
- using __set_value_t =
- completion_signatures<set_value_t(const decay_t<_Tys>&...)>;
-
- template <class _Ty>
- using __set_error_t =
- completion_signatures<set_error_t(const decay_t<_Ty>&)>;
-
- template <class _Self>
- using __completions_t = make_completion_signatures<
- _Sender&, __env_t<__make_dependent_on<_Env, _Self>>,
- completion_signatures<set_error_t(const std::exception_ptr&),
- set_stopped_t()>, // NOT TO SPEC
- __set_value_t, __set_error_t>;
-
- _Sender __sndr_;
- std::shared_ptr<__sh_state_> __shared_state_;
-
- public:
- template <__decays_to<__sender> _Self,
- receiver_of<__completions_t<_Self>> _Receiver>
- friend auto
- tag_invoke(connect_t, _Self&& __self, _Receiver&& __recvr) noexcept(
- std::is_nothrow_constructible_v<decay_t<_Receiver>, _Receiver>)
- -> __operation<_Receiver>
+ class __t
{
- return __operation<_Receiver>{(_Receiver &&) __recvr,
- __self.__shared_state_};
- }
+ using __sh_state_ = stdexec::__t<__sh_state<_SenderId, _EnvId>>;
- template <tag_category<forwarding_sender_query> _Tag, class... _As>
- requires(!__is_instance_of<_Tag, get_completion_scheduler_t>) &&
- __callable<_Tag, const _Sender&, _As...>
- friend auto tag_invoke(
- _Tag __tag, const __sender& __self,
- _As&&... __as) noexcept(__nothrow_callable<_Tag,
- const _Sender&,
- _As...>)
- -> __call_result_if_t<
- tag_category<_Tag, forwarding_sender_query>, _Tag,
- const _Sender&, _As...>
- {
- return ((_Tag &&) __tag)(__self.__sndr_, (_As &&) __as...);
- }
+ template <class... _Tys>
+ using __set_value_t =
+ completion_signatures<set_value_t(const decay_t<_Tys>&...)>;
- template <__decays_to<__sender> _Self, class _OtherEnv>
- friend auto tag_invoke(get_completion_signatures_t, _Self&&, _OtherEnv)
- -> __completions_t<_Self>;
+ template <class _Ty>
+ using __set_error_t =
+ completion_signatures<set_error_t(const decay_t<_Ty>&)>;
- explicit __sender(_Sender __sndr, _Env __env) :
- __sndr_((_Sender &&) __sndr),
- __shared_state_{std::make_shared<__sh_state_>(__sndr_, (_Env &&) __env)}
- {}
+ template <class _Self>
+ using __completions_t = make_completion_signatures<
+ _Sender&, __env_t<__make_dependent_on<_Env, _Self>>,
+ completion_signatures<set_error_t(const std::exception_ptr&),
+ set_stopped_t()>, // NOT TO SPEC
+ __set_value_t, __set_error_t>;
+
+ _Sender __sndr_;
+ std::shared_ptr<__sh_state_> __shared_state_;
+
+ public:
+ using __id = __sender;
+
+ template <__decays_to<__t> _Self,
+ receiver_of<__completions_t<_Self>> _Receiver>
+ friend auto
+ tag_invoke(connect_t, _Self&& __self, _Receiver __recvr) noexcept(
+ std::is_nothrow_move_constructible_v<_Receiver>)
+ -> __operation<_Receiver>
+ {
+ return __operation<_Receiver>{(_Receiver &&) __recvr,
+ __self.__shared_state_};
+ }
+
+ template <tag_category<forwarding_sender_query> _Tag, class... _As>
+ requires(!__is_instance_of<_Tag, get_completion_scheduler_t>) &&
+ __callable<_Tag, const _Sender&, _As...>
+ friend auto tag_invoke(
+ _Tag __tag, const __t& __self,
+ _As&&... __as) noexcept(__nothrow_callable<_Tag,
+ const _Sender&,
+ _As...>)
+ -> __call_result_if_t<
+ tag_category<_Tag, forwarding_sender_query>, _Tag,
+ const _Sender&, _As...>
+ {
+ return ((_Tag &&) __tag)(__self.__sndr_, (_As &&) __as...);
+ }
+
+ template <__decays_to<__t> _Self, class _OtherEnv>
+ friend auto tag_invoke(get_completion_signatures_t, _Self&&, _OtherEnv)
+ -> __completions_t<_Self>;
+
+ explicit __t(_Sender __sndr, _Env __env) :
+ __sndr_((_Sender &&) __sndr), __shared_state_{
+ std::make_shared<__sh_state_>(
+ __sndr_, (_Env &&) __env)}
+ {}
+ };
};
struct split_t;
// When looking for user-defined customizations of split, these
// are the signatures to test against, in order:
-template <class _Sender, class _Env>
-using __cust_sigs = __msignatures<
+using _Sender = __0;
+using _Env = __1;
+using __cust_sigs = __types<
tag_invoke_t(split_t, get_completion_scheduler_t<set_value_t>(_Sender&),
_Sender),
tag_invoke_t(split_t, get_completion_scheduler_t<set_value_t>(_Sender&),
@@ -3614,27 +3665,20 @@
template <class _Sender, class _Env>
inline constexpr bool __is_split_customized =
- __v<__many_well_formed<__cust_sigs<_Sender, _Env>>>;
+ __minvocable<__which<__cust_sigs>, _Sender, _Env>;
template <class _Sender, class _Env>
-using __sender_t =
- __sender<__x<remove_cvref_t<_Sender>>, __x<remove_cvref_t<_Env>>>;
+using __sender_t = __t<__sender<stdexec::__id<remove_cvref_t<_Sender>>,
+ stdexec::__id<remove_cvref_t<_Env>>>>;
template <class _Sender, class _Env>
-using __receiver_t =
- __receiver<__x<remove_cvref_t<_Sender>>, __x<remove_cvref_t<_Env>>>;
+using __receiver_t = __t<__receiver<stdexec::__id<remove_cvref_t<_Sender>>,
+ stdexec::__id<remove_cvref_t<_Env>>>>;
template <class _Sender, class _Env>
-using __construct_sender = __mconstruct<__sender_t<_Sender, _Env>>(_Sender,
- _Env);
-
-template <class _Sender, class _Env>
-using __which_t =
- __mwhich_t<__cust_sigs<_Sender, _Env>, __construct_sender<_Sender, _Env>>;
-
-template <class _Sender, class _Env>
-using __which_i =
- __mwhich_i<__cust_sigs<_Sender, _Env>, __construct_sender<_Sender, _Env>>;
+using __dispatcher_for =
+ __make_dispatcher<__cust_sigs, __mconstructor_for<__sender_t>, _Sender,
+ _Env>;
struct split_t
{
@@ -3643,47 +3687,13 @@
sender_to<_Sender&, __receiver_t<_Sender, _Env>>) ||
__is_split_customized<_Sender, _Env>
auto operator()(_Sender&& __sndr, _Env&& __env = _Env{}) const
- noexcept(__mnoexcept_v<__which_t<_Sender, _Env>>)
- -> __mtypeof<__which_t<_Sender, _Env>>
+ noexcept(__nothrow_callable<__dispatcher_for<_Sender, _Env>,
+ _Sender, _Env>)
+ -> __call_result_t<__dispatcher_for<_Sender, _Env>, _Sender,
+ _Env>
{
- constexpr auto __idx = __v<__which_i<_Sender, _Env>>;
- // Dispatch to the correct implementation:
- if constexpr (__idx == 0)
- {
- auto __sched = get_completion_scheduler<set_value_t>(__sndr);
- return tag_invoke(split_t{}, std::move(__sched),
- (_Sender &&) __sndr);
- }
- else if constexpr (__idx == 1)
- {
- auto __sched = get_completion_scheduler<set_value_t>(__sndr);
- return tag_invoke(split_t{}, std::move(__sched),
- (_Sender &&) __sndr, (_Env &&) __env);
- }
- else if constexpr (__idx == 2)
- {
- return tag_invoke(split_t{}, get_scheduler(__env),
- (_Sender &&) __sndr);
- }
- else if constexpr (__idx == 3)
- {
- auto __sched = get_scheduler(__env);
- return tag_invoke(split_t{}, std::move(__sched),
- (_Sender &&) __sndr, (_Env &&) __env);
- }
- else if constexpr (__idx == 4)
- {
- return tag_invoke(split_t{}, (_Sender &&) __sndr);
- }
- else if constexpr (__idx == 5)
- {
- return tag_invoke(split_t{}, (_Sender &&) __sndr, (_Env &&) __env);
- }
- else
- {
- return __sender_t<_Sender, _Env>{(_Sender &&) __sndr,
- (_Env &&) __env};
- }
+ return __dispatcher_for<_Sender, _Env>{}((_Sender &&) __sndr,
+ (_Env &&) __env);
}
__binder_back<split_t> operator()() const
@@ -3701,52 +3711,59 @@
{
template <class _BaseEnv>
using __env_t = __make_env_t<_BaseEnv, // NOT TO SPEC
- __with_t<get_stop_token_t, in_place_stop_token>>;
+ __with<get_stop_token_t, in_place_stop_token>>;
template <class _SenderId, class _EnvId>
struct __sh_state;
template <class _SenderId, class _EnvId>
-class __receiver
+struct __receiver
{
- using _Sender = __t<_SenderId>;
- using _Env = __t<_EnvId>;
- __intrusive_ptr<__sh_state<_SenderId, _EnvId>> __shared_state_;
+ using _Sender = stdexec::__t<_SenderId>;
+ using _Env = stdexec::__t<_EnvId>;
- public:
- explicit __receiver(__sh_state<_SenderId, _EnvId>& __shared_state) noexcept
- :
- __shared_state_(__shared_state.__intrusive_from_this())
- {}
-
- template <__one_of<set_value_t, set_error_t, set_stopped_t> _Tag,
- class... _As>
- friend void tag_invoke(_Tag __tag, __receiver&& __self,
- _As&&... __as) noexcept
+ class __t
{
- __sh_state<_SenderId, _EnvId>& __state = *__self.__shared_state_;
+ __intrusive_ptr<stdexec::__t<__sh_state<_SenderId, _EnvId>>>
+ __shared_state_;
- try
+ public:
+ using __id = __receiver;
+ explicit __t(stdexec::__t<__sh_state<_SenderId, _EnvId>>&
+ __shared_state) noexcept :
+ __shared_state_(__shared_state.__intrusive_from_this())
+ {}
+
+ template <__one_of<set_value_t, set_error_t, set_stopped_t> _Tag,
+ class... _As>
+ friend void tag_invoke(_Tag __tag, __t&& __self, _As&&... __as) noexcept
{
- using __tuple_t = __decayed_tuple<_Tag, _As...>;
- __state.__data_.template emplace<__tuple_t>(__tag,
- (_As &&) __as...);
- }
- catch (...)
- {
- using __tuple_t = __decayed_tuple<set_error_t, std::exception_ptr>;
- __state.__data_.template emplace<__tuple_t>(
- set_error, std::current_exception());
+ stdexec::__t<__sh_state<_SenderId, _EnvId>>& __state =
+ *__self.__shared_state_;
+
+ try
+ {
+ using __tuple_t = __decayed_tuple<_Tag, _As...>;
+ __state.__data_.template emplace<__tuple_t>(__tag,
+ (_As &&) __as...);
+ }
+ catch (...)
+ {
+ using __tuple_t =
+ __decayed_tuple<set_error_t, std::exception_ptr>;
+ __state.__data_.template emplace<__tuple_t>(
+ set_error, std::current_exception());
+ }
+
+ __state.__notify();
+ __self.__shared_state_.reset();
}
- __state.__notify();
- __self.__shared_state_.reset();
- }
-
- friend const __env_t<_Env>& tag_invoke(get_env_t, const __receiver& __self)
- {
- return __self.__shared_state_->__env_;
- }
+ friend const __env_t<_Env>& tag_invoke(get_env_t, const __t& __self)
+ {
+ return __self.__shared_state_->__env_;
+ }
+ };
};
struct __operation_base
@@ -3756,249 +3773,269 @@
};
template <class _SenderId, class _EnvId>
-struct __sh_state : __enable_intrusive_from_this<__sh_state<_SenderId, _EnvId>>
+struct __sh_state
{
- using _Sender = __t<_SenderId>;
- using _Env = __t<_EnvId>;
+ using _Sender = stdexec::__t<_SenderId>;
+ using _Env = stdexec::__t<_EnvId>;
- template <class... _Ts>
- using __bind_tuples =
- __mbind_front_q<__variant,
- std::tuple<set_stopped_t>, // Initial state of the
- // variant is set_stopped
- std::tuple<set_error_t, std::exception_ptr>, _Ts...>;
-
- using __bound_values_t =
- __value_types_of_t<_Sender, __env_t<_Env>,
- __mbind_front_q<__decayed_tuple, set_value_t>,
- __q<__bind_tuples>>;
-
- using __variant_t = __error_types_of_t<
- _Sender, __env_t<_Env>,
- __transform<__mbind_front_q<__decayed_tuple, set_error_t>,
- __bound_values_t>>;
-
- using __receiver_t = __receiver<_SenderId, _EnvId>;
-
- __variant_t __data_;
- in_place_stop_source __stop_source_{};
-
- std::atomic<void*> __op_state1_{nullptr};
- __env_t<_Env> __env_;
- connect_result_t<_Sender&, __receiver_t> __op_state2_;
-
- explicit __sh_state(_Sender& __sndr, _Env __env) :
- __env_(__make_env((_Env &&) __env,
- __with(get_stop_token, __stop_source_.get_token()))),
- __op_state2_(connect(__sndr, __receiver_t{*this}))
+ struct __t : __enable_intrusive_from_this<__t>
{
- start(__op_state2_);
- }
+ using __id = __sh_state;
- void __notify() noexcept
- {
- void* const __completion_state = static_cast<void*>(this);
- void* const __old = __op_state1_.exchange(__completion_state,
- std::memory_order_acq_rel);
- if (__old != nullptr)
+ template <class... _Ts>
+ using __bind_tuples =
+ __mbind_front_q<__variant,
+ std::tuple<set_stopped_t>, // Initial state of the
+ // variant is set_stopped
+ std::tuple<set_error_t, std::exception_ptr>,
+ _Ts...>;
+
+ using __bound_values_t =
+ __value_types_of_t<_Sender, __env_t<_Env>,
+ __mbind_front_q<__decayed_tuple, set_value_t>,
+ __q<__bind_tuples>>;
+
+ using __variant_t = __error_types_of_t<
+ _Sender, __env_t<_Env>,
+ __transform<__mbind_front_q<__decayed_tuple, set_error_t>,
+ __bound_values_t>>;
+
+ using __receiver_t = stdexec::__t<__receiver<_SenderId, _EnvId>>;
+
+ __variant_t __data_;
+ in_place_stop_source __stop_source_{};
+
+ std::atomic<void*> __op_state1_{nullptr};
+ __env_t<_Env> __env_;
+ connect_result_t<_Sender&, __receiver_t> __op_state2_;
+
+ explicit __t(_Sender& __sndr, _Env __env) :
+ __env_(__make_env(
+ (_Env &&) __env,
+ __with_(get_stop_token, __stop_source_.get_token()))),
+ __op_state2_(connect(__sndr, __receiver_t{*this}))
{
- auto* __op = static_cast<__operation_base*>(__old);
- __op->__notify_(__op);
+ start(__op_state2_);
}
- }
- void __detach() noexcept
- {
- __stop_source_.request_stop();
- }
-};
+ void __notify() noexcept
+ {
+ void* const __completion_state = static_cast<void*>(this);
+ void* const __old = __op_state1_.exchange(
+ __completion_state, std::memory_order_acq_rel);
+ if (__old != nullptr)
+ {
+ auto* __op = static_cast<__operation_base*>(__old);
+ __op->__notify_(__op);
+ }
+ }
-template <class _SenderId, class _EnvId, class _ReceiverId>
-class __operation : public __operation_base
-{
- using _Sender = __t<_SenderId>;
- using _Env = __t<_EnvId>;
- using _Receiver = __t<_ReceiverId>;
-
- struct __on_stop_requested
- {
- in_place_stop_source& __stop_source_;
- void operator()() noexcept
+ void __detach() noexcept
{
__stop_source_.request_stop();
}
};
- using __on_stop = std::optional<typename stop_token_of_t<
- env_of_t<_Receiver>&>::template callback_type<__on_stop_requested>>;
+};
- _Receiver __rcvr_;
- __on_stop __on_stop_{};
- __intrusive_ptr<__sh_state<_SenderId, _EnvId>> __shared_state_;
+template <class _SenderId, class _EnvId, class _ReceiverId>
+struct __operation
+{
+ using _Sender = stdexec::__t<_SenderId>;
+ using _Env = stdexec::__t<_EnvId>;
+ using _Receiver = stdexec::__t<_ReceiverId>;
- public:
- __operation(
- _Receiver __rcvr,
- __intrusive_ptr<__sh_state<_SenderId, _EnvId>>
- __shared_state) noexcept(std::
- is_nothrow_move_constructible_v<
- _Receiver>) :
- __operation_base{__notify},
- __rcvr_((_Receiver &&) __rcvr),
- __shared_state_(std::move(__shared_state))
- {}
- ~__operation()
+ class __t : public __operation_base
{
- // Check to see if this operation was ever started. If not,
- // detach the (potentially still running) operation:
- if (nullptr ==
- __shared_state_->__op_state1_.load(std::memory_order_acquire))
+ struct __on_stop_requested
{
- __shared_state_->__detach();
- }
- }
- STDEXEC_IMMOVABLE(__operation);
-
- static void __notify(__operation_base* __self) noexcept
- {
- __operation* __op = static_cast<__operation*>(__self);
- __op->__on_stop_.reset();
-
- std::visit(
- [&](auto& __tupl) noexcept -> void {
- std::apply(
- [&](auto __tag, auto&... __args) noexcept -> void {
- __tag((_Receiver &&) __op->__rcvr_,
- std::move(__args)...);
- },
- __tupl);
- },
- __op->__shared_state_->__data_);
- }
-
- friend void tag_invoke(start_t, __operation& __self) noexcept
- {
- __sh_state<_SenderId, _EnvId>* __shared_state =
- __self.__shared_state_.get();
- std::atomic<void*>& __op_state1 = __shared_state->__op_state1_;
- void* const __completion_state = static_cast<void*>(__shared_state);
- void* const __old = __op_state1.load(std::memory_order_acquire);
- if (__old == __completion_state)
- {
- __self.__notify(&__self);
- }
- else
- {
- // register stop callback:
- __self.__on_stop_.emplace(
- get_stop_token(get_env(__self.__rcvr_)),
- __on_stop_requested{__shared_state->__stop_source_});
- // Check if the stop_source has requested cancellation
- if (__shared_state->__stop_source_.stop_requested())
+ in_place_stop_source& __stop_source_;
+ void operator()() noexcept
{
- // Stop has already been requested. Don't bother starting
- // the child operations.
- stdexec::set_stopped((_Receiver &&) __self.__rcvr_);
+ __stop_source_.request_stop();
+ }
+ };
+ using __on_stop = std::optional<typename stop_token_of_t<
+ env_of_t<_Receiver>&>::template callback_type<__on_stop_requested>>;
+
+ _Receiver __rcvr_;
+ __on_stop __on_stop_{};
+ __intrusive_ptr<stdexec::__t<__sh_state<_SenderId, _EnvId>>>
+ __shared_state_;
+
+ public:
+ using __id = __operation;
+ __t(_Receiver __rcvr,
+ __intrusive_ptr<stdexec::__t<__sh_state<_SenderId, _EnvId>>>
+ __shared_state) noexcept(std::
+ is_nothrow_move_constructible_v<
+ _Receiver>) :
+ __operation_base{__notify},
+ __rcvr_((_Receiver &&) __rcvr),
+ __shared_state_(std::move(__shared_state))
+ {}
+ ~__t()
+ {
+ // Check to see if this operation was ever started. If not,
+ // detach the (potentially still running) operation:
+ if (nullptr ==
+ __shared_state_->__op_state1_.load(std::memory_order_acquire))
+ {
+ __shared_state_->__detach();
+ }
+ }
+ STDEXEC_IMMOVABLE(__t);
+
+ static void __notify(__operation_base* __self) noexcept
+ {
+ __t* __op = static_cast<__t*>(__self);
+ __op->__on_stop_.reset();
+
+ std::visit(
+ [&](auto& __tupl) noexcept -> void {
+ std::apply(
+ [&](auto __tag, auto&... __args) noexcept -> void {
+ __tag((_Receiver &&) __op->__rcvr_,
+ std::move(__args)...);
+ },
+ __tupl);
+ },
+ __op->__shared_state_->__data_);
+ }
+
+ friend void tag_invoke(start_t, __t& __self) noexcept
+ {
+ stdexec::__t<__sh_state<_SenderId, _EnvId>>* __shared_state =
+ __self.__shared_state_.get();
+ std::atomic<void*>& __op_state1 = __shared_state->__op_state1_;
+ void* const __completion_state = static_cast<void*>(__shared_state);
+ void* const __old = __op_state1.load(std::memory_order_acquire);
+ if (__old == __completion_state)
+ {
+ __self.__notify(&__self);
}
else
{
- // Otherwise, the inner source hasn't notified completion.
- // Set this operation as the __op_state1 so it's notified.
- void* __old = nullptr;
- if (!__op_state1.compare_exchange_weak(
- __old, &__self, std::memory_order_release,
- std::memory_order_acquire))
+ // register stop callback:
+ __self.__on_stop_.emplace(
+ get_stop_token(get_env(__self.__rcvr_)),
+ __on_stop_requested{__shared_state->__stop_source_});
+ // Check if the stop_source has requested cancellation
+ if (__shared_state->__stop_source_.stop_requested())
{
- // We get here when the task completed during the execution
- // of this function. Complete the operation synchronously.
- STDEXEC_ASSERT(__old == __completion_state);
- __self.__notify(&__self);
+ // Stop has already been requested. Don't bother starting
+ // the child operations.
+ stdexec::set_stopped((_Receiver &&) __self.__rcvr_);
+ }
+ else
+ {
+ // Otherwise, the inner source hasn't notified completion.
+ // Set this operation as the __op_state1 so it's notified.
+ void* __old = nullptr;
+ if (!__op_state1.compare_exchange_weak(
+ __old, &__self, std::memory_order_release,
+ std::memory_order_acquire))
+ {
+ // We get here when the task completed during the
+ // execution of this function. Complete the operation
+ // synchronously.
+ STDEXEC_ASSERT(__old == __completion_state);
+ __self.__notify(&__self);
+ }
}
}
}
- }
+ };
};
template <class _SenderId, class _EnvId>
-class __sender
+struct __sender
{
- using _Sender = __t<_SenderId>;
- using _Env = __t<_EnvId>;
- using __sh_state_ = __sh_state<_SenderId, _EnvId>;
- template <class _Receiver>
- using __operation =
- __operation<_SenderId, _EnvId, __x<remove_cvref_t<_Receiver>>>;
+ using _Sender = stdexec::__t<_SenderId>;
+ using _Env = stdexec::__t<_EnvId>;
- template <class... _Tys>
- using __set_value_t =
- completion_signatures<set_value_t(decay_t<_Tys>&&...)>;
-
- template <class _Ty>
- using __set_error_t = completion_signatures<set_error_t(decay_t<_Ty>&&)>;
-
- template <class _Self>
- using __completions_t = make_completion_signatures<
- _Sender&, __env_t<__make_dependent_on<_Env, _Self>>,
- completion_signatures<set_error_t(std::exception_ptr&&),
- set_stopped_t()>, // BUGBUG NOT TO SPEC
- __set_value_t, __set_error_t>;
-
- _Sender __sndr_;
- __intrusive_ptr<__sh_state_> __shared_state_;
-
- template <same_as<__sender> _Self,
- receiver_of<__completions_t<_Self>> _Receiver>
- friend auto
- tag_invoke(connect_t, _Self&& __self, _Receiver&& __rcvr) noexcept(
- std::is_nothrow_constructible_v<decay_t<_Receiver>, _Receiver>)
- -> __operation<_Receiver>
+ class __t
{
- return __operation<_Receiver>{(_Receiver &&) __rcvr,
- std::move(__self).__shared_state_};
- }
+ using __sh_state_ = stdexec::__t<__sh_state<_SenderId, _EnvId>>;
+ template <class _Receiver>
+ using __operation = stdexec::__t<
+ __operation<_SenderId, _EnvId, stdexec::__id<_Receiver>>>;
- template <tag_category<forwarding_sender_query> _Tag, class... _As>
- requires(!__is_instance_of<_Tag, get_completion_scheduler_t>) &&
- __callable<_Tag, const _Sender&, _As...>
- friend auto tag_invoke(
- _Tag __tag, const __sender& __self,
- _As&&... __as) noexcept(__nothrow_callable<_Tag,
- const _Sender&,
- _As...>)
- -> __call_result_if_t<
- tag_category<_Tag, forwarding_sender_query>, _Tag,
- const _Sender&, _As...>
- {
- return ((_Tag &&) __tag)(__self.__sndr_, (_As &&) __as...);
- }
+ template <class... _Tys>
+ using __set_value_t =
+ completion_signatures<set_value_t(decay_t<_Tys>&&...)>;
- template <same_as<__sender> _Self, class _OtherEnv>
- friend auto tag_invoke(get_completion_signatures_t, _Self&&, _OtherEnv)
- -> __completions_t<_Self>;
+ template <class _Ty>
+ using __set_error_t =
+ completion_signatures<set_error_t(decay_t<_Ty>&&)>;
- public:
- explicit __sender(_Sender __sndr, _Env __env) :
- __sndr_((_Sender &&) __sndr),
- __shared_state_{__make_intrusive<__sh_state_>(__sndr_, (_Env &&) __env)}
- {}
- ~__sender()
- {
- if (nullptr != __shared_state_)
+ template <class _Self>
+ using __completions_t = make_completion_signatures<
+ _Sender&, __env_t<__make_dependent_on<_Env, _Self>>,
+ completion_signatures<set_error_t(std::exception_ptr&&),
+ set_stopped_t()>, // BUGBUG NOT TO SPEC
+ __set_value_t, __set_error_t>;
+
+ _Sender __sndr_;
+ __intrusive_ptr<__sh_state_> __shared_state_;
+
+ template <same_as<__t> _Self,
+ receiver_of<__completions_t<_Self>> _Receiver>
+ friend auto
+ tag_invoke(connect_t, _Self&& __self, _Receiver __rcvr) noexcept(
+ std::is_nothrow_move_constructible_v<_Receiver>)
+ -> __operation<_Receiver>
{
- // We're detaching a potentially running operation. Request
- // cancellation.
- __shared_state_->__detach(); // BUGBUG NOT TO SPEC
+ return __operation<_Receiver>{(_Receiver &&) __rcvr,
+ std::move(__self).__shared_state_};
}
- }
- // Move-only:
- __sender(__sender&&) = default;
+
+ template <tag_category<forwarding_sender_query> _Tag, class... _As>
+ requires(!__is_instance_of<_Tag, get_completion_scheduler_t>) &&
+ __callable<_Tag, const _Sender&, _As...>
+ friend auto tag_invoke(
+ _Tag __tag, const __t& __self,
+ _As&&... __as) noexcept(__nothrow_callable<_Tag,
+ const _Sender&,
+ _As...>)
+ -> __call_result_if_t<
+ tag_category<_Tag, forwarding_sender_query>, _Tag,
+ const _Sender&, _As...>
+ {
+ return ((_Tag &&) __tag)(__self.__sndr_, (_As &&) __as...);
+ }
+
+ template <same_as<__t> _Self, class _OtherEnv>
+ friend auto tag_invoke(get_completion_signatures_t, _Self&&, _OtherEnv)
+ -> __completions_t<_Self>;
+
+ public:
+ using __id = __sender;
+ explicit __t(_Sender __sndr, _Env __env) :
+ __sndr_((_Sender &&) __sndr), __shared_state_{
+ __make_intrusive<__sh_state_>(
+ __sndr_, (_Env &&) __env)}
+ {}
+ ~__t()
+ {
+ if (nullptr != __shared_state_)
+ {
+ // We're detaching a potentially running operation. Request
+ // cancellation.
+ __shared_state_->__detach(); // BUGBUG NOT TO SPEC
+ }
+ }
+ // Move-only:
+ __t(__t&&) = default;
+ };
};
struct ensure_started_t;
// When looking for user-defined customizations of split, these
// are the signatures to test against, in order:
-template <class _Sender, class _Env>
-using __cust_sigs = __msignatures<
+using _Sender = __0;
+using _Env = __1;
+using __cust_sigs = __types<
tag_invoke_t(ensure_started_t,
get_completion_scheduler_t<set_value_t>(_Sender&), _Sender),
tag_invoke_t(ensure_started_t,
@@ -4011,27 +4048,20 @@
template <class _Sender, class _Env>
inline constexpr bool __is_ensure_started_customized =
- __v<__many_well_formed<__cust_sigs<_Sender, _Env>>>;
+ __minvocable<__which<__cust_sigs>, _Sender, _Env>;
template <class _Sender, class _Env>
-using __sender_t =
- __sender<__x<remove_cvref_t<_Sender>>, __x<remove_cvref_t<_Env>>>;
+using __sender_t = __t<__sender<stdexec::__id<remove_cvref_t<_Sender>>,
+ stdexec::__id<remove_cvref_t<_Env>>>>;
template <class _Sender, class _Env>
-using __receiver_t =
- __receiver<__x<remove_cvref_t<_Sender>>, __x<remove_cvref_t<_Env>>>;
+using __receiver_t = __t<__receiver<stdexec::__id<remove_cvref_t<_Sender>>,
+ stdexec::__id<remove_cvref_t<_Env>>>>;
template <class _Sender, class _Env>
-using __construct_sender = __mconstruct<__sender_t<_Sender, _Env>>(_Sender,
- _Env);
-
-template <class _Sender, class _Env>
-using __which_t =
- __mwhich_t<__cust_sigs<_Sender, _Env>, __construct_sender<_Sender, _Env>>;
-
-template <class _Sender, class _Env>
-using __which_i =
- __mwhich_i<__cust_sigs<_Sender, _Env>, __construct_sender<_Sender, _Env>>;
+using __dispatcher_for =
+ __make_dispatcher<__cust_sigs, __mconstructor_for<__sender_t>, _Sender,
+ _Env>;
struct ensure_started_t
{
@@ -4039,53 +4069,20 @@
requires(copy_constructible<remove_cvref_t<_Sender>> &&
sender_to<_Sender&, __receiver_t<_Sender, _Env>>) ||
__is_ensure_started_customized<_Sender, _Env>
- auto operator()(_Sender&& __sndr, _Env&& __env = _Env{}) const
- noexcept(__mnoexcept_v<__which_t<_Sender, _Env>>)
- { //-> __mtypeof<__which_t<_Sender, _Env>> {
- constexpr auto __idx = __v<__which_i<_Sender, _Env>>;
- // Dispatch to the correct implementation:
- if constexpr (__idx == 0)
- {
- auto __sched = get_completion_scheduler<set_value_t>(__sndr);
- return tag_invoke(ensure_started_t{}, std::move(__sched),
- (_Sender &&) __sndr);
- }
- else if constexpr (__idx == 1)
- {
- auto __sched = get_completion_scheduler<set_value_t>(__sndr);
- return tag_invoke(ensure_started_t{}, std::move(__sched),
- (_Sender &&) __sndr, (_Env &&) __env);
- }
- else if constexpr (__idx == 2)
- {
- return tag_invoke(ensure_started_t{}, get_scheduler(__env),
- (_Sender &&) __sndr);
- }
- else if constexpr (__idx == 3)
- {
- auto __sched = get_scheduler(__env);
- return tag_invoke(ensure_started_t{}, std::move(__sched),
- (_Sender &&) __sndr, (_Env &&) __env);
- }
- else if constexpr (__idx == 4)
- {
- return tag_invoke(ensure_started_t{}, (_Sender &&) __sndr);
- }
- else if constexpr (__idx == 5)
- {
- return tag_invoke(ensure_started_t{}, (_Sender &&) __sndr,
- (_Env &&) __env);
- }
- else
- {
- return __sender_t<_Sender, _Env>{(_Sender &&) __sndr,
- (_Env &&) __env};
- }
+ auto operator()(_Sender&& __sndr, _Env&& __env = _Env{}) const
+ noexcept(__nothrow_callable<__dispatcher_for<_Sender, _Env>,
+ _Sender, _Env>)
+ -> __call_result_t<__dispatcher_for<_Sender, _Env>, _Sender,
+ _Env>
+ {
+ return __dispatcher_for<_Sender, _Env>{}((_Sender &&) __sndr,
+ (_Env &&) __env);
}
+ // BUGBUG this will never match
template <class _SenderId, class _EnvId>
- __sender<_SenderId, _EnvId>
- operator()(__sender<_SenderId, _EnvId> __sndr) const
+ __t<__sender<_SenderId, _EnvId>>
+ operator()(__t<__sender<_SenderId, _EnvId>> __sndr) const
{
return std::move(__sndr);
}
@@ -4110,10 +4107,10 @@
template <class _Fun>
using __result_sender =
- __transform<__q1<__decay_ref>, __mbind_front_q<__call_result_t, _Fun>>;
+ __transform<__q<__decay_ref>, __mbind_front_q<__call_result_t, _Fun>>;
template <class _Receiver, class _Fun>
-using __op_state_for = __mcompose<__mbind_back_q1<connect_result_t, _Receiver>,
+using __op_state_for = __mcompose<__mbind_back_q<connect_result_t, _Receiver>,
__result_sender<_Fun>>;
template <class _Set, class _Sig>
@@ -4134,163 +4131,184 @@
};
template <class _Env, class _Fun, class _Set, class _Sig>
-using __tfx_signal_t = __minvoke2<__tfx_signal_<_Set, _Sig>, _Env, _Fun>;
+using __tfx_signal_t = __minvoke<__tfx_signal_<_Set, _Sig>, _Env, _Fun>;
-template <class _ReceiverId, class _FunId, class _Let, class... _Tuples>
-struct __operation_base_ : __immovable
+template <class _ReceiverId, class _Fun, class _Let, class... _Tuples>
+struct __operation_base_
{
- using _Receiver = __t<_ReceiverId>;
- using _Fun = __t<_FunId>;
+ using _Receiver = stdexec::__t<_ReceiverId>;
- using __results_variant_t = std::variant<std::monostate, _Tuples...>;
- using __op_state_variant_t =
- __minvoke<__transform<__uncurry<__op_state_for<_Receiver, _Fun>>,
- __nullable_variant_t>,
- _Tuples...>;
+ struct __t : __immovable
+ {
+ using __id = __operation_base_;
+ using __results_variant_t = std::variant<std::monostate, _Tuples...>;
+ using __op_state_variant_t =
+ __minvoke<__transform<__uncurry<__op_state_for<_Receiver, _Fun>>,
+ __nullable_variant_t>,
+ _Tuples...>;
- _Receiver __rcvr_;
- _Fun __fun_;
- __results_variant_t __args_;
- __op_state_variant_t __op_state3_;
+ _Receiver __rcvr_;
+ _Fun __fun_;
+ __results_variant_t __args_;
+ __op_state_variant_t __op_state3_;
+ };
};
-template <class _ReceiverId, class _FunId, class _Let, class... _Tuples>
+template <class _ReceiverId, class _Fun, class _Let, class... _Tuples>
struct __receiver_
{
- using _Receiver = __t<_ReceiverId>;
- using _Fun = __t<_FunId>;
+ using _Receiver = stdexec::__t<_ReceiverId>;
using _Env = env_of_t<_Receiver>;
- template <__one_of<_Let> _Tag, class... _As>
- requires __minvocable<__result_sender<_Fun>, _As...> &&
- sender_to<__minvoke<__result_sender<_Fun>, _As...>, _Receiver>
- friend void tag_invoke(_Tag, __receiver_&& __self, _As&&... __as) noexcept
- try
+ struct __t
{
- using __tuple_t = __decayed_tuple<_As...>;
- using __op_state_t = __minvoke<__op_state_for<_Receiver, _Fun>, _As...>;
- auto& __args = __self.__op_state_->__args_.template emplace<__tuple_t>(
- (_As &&) __as...);
- auto& __op =
- __self.__op_state_->__op_state3_.template emplace<__op_state_t>(
- __conv{[&] {
- return connect(
- std::apply(std::move(__self.__op_state_->__fun_),
- __args),
- std::move(__self.__op_state_->__rcvr_));
- }});
- start(__op);
- }
- catch (...)
- {
- set_error(std::move(__self.__op_state_->__rcvr_),
- std::current_exception());
- }
+ using __id = __receiver_;
- template <__one_of<set_value_t, set_error_t, set_stopped_t> _Tag,
- class... _As>
- requires __none_of<_Tag, _Let> && __callable<_Tag, _Receiver, _As...>
- friend void tag_invoke(_Tag __tag, __receiver_&& __self,
- _As&&... __as) noexcept
- {
- __tag(std::move(__self.__op_state_->__rcvr_), (_As &&) __as...);
- }
+ template <__one_of<_Let> _Tag, class... _As>
+ requires __minvocable<__result_sender<_Fun>, _As...> &&
+ sender_to<__minvoke<__result_sender<_Fun>, _As...>,
+ _Receiver>
+ friend void tag_invoke(_Tag, __t&& __self, _As&&... __as) noexcept
+ try
+ {
+ using __tuple_t = __decayed_tuple<_As...>;
+ using __op_state_t =
+ __minvoke<__op_state_for<_Receiver, _Fun>, _As...>;
+ auto& __args =
+ __self.__op_state_->__args_.template emplace<__tuple_t>(
+ (_As &&) __as...);
+ auto& __op =
+ __self.__op_state_->__op_state3_.template emplace<__op_state_t>(
+ __conv{[&] {
+ return connect(
+ std::apply(std::move(__self.__op_state_->__fun_),
+ __args),
+ std::move(__self.__op_state_->__rcvr_));
+ }});
+ start(__op);
+ }
+ catch (...)
+ {
+ set_error(std::move(__self.__op_state_->__rcvr_),
+ std::current_exception());
+ }
- friend auto tag_invoke(get_env_t, const __receiver_& __self)
- -> env_of_t<_Receiver>
- {
- return get_env(__self.__op_state_->__rcvr_);
- }
+ template <__one_of<set_value_t, set_error_t, set_stopped_t> _Tag,
+ class... _As>
+ requires __none_of<_Tag, _Let> &&
+ __callable<_Tag, _Receiver, _As...>
+ friend void tag_invoke(_Tag __tag, __t&& __self, _As&&... __as) noexcept
+ {
+ __tag(std::move(__self.__op_state_->__rcvr_), (_As &&) __as...);
+ }
- using __operation_base_t =
- __operation_base_<_ReceiverId, _FunId, _Let, _Tuples...>;
- __operation_base_t* __op_state_;
+ friend auto tag_invoke(get_env_t, const __t& __self)
+ -> env_of_t<_Receiver>
+ {
+ return get_env(__self.__op_state_->__rcvr_);
+ }
+
+ using __operation_base_t = stdexec::__t<
+ __operation_base_<_ReceiverId, _Fun, _Let, _Tuples...>>;
+ __operation_base_t* __op_state_;
+ };
};
-template <class _SenderId, class _ReceiverId, class _FunId, class _Let>
-using __receiver = __gather_sigs_t<
+template <class _SenderId, class _ReceiverId, class _Fun, class _Let>
+using __receiver = stdexec::__t<__gather_completions_for<
_Let, __t<_SenderId>, env_of_t<__t<_ReceiverId>>, __q<__decayed_tuple>,
- __munique<__mbind_front_q<__receiver_, _ReceiverId, _FunId, _Let>>>;
+ __munique<__mbind_front_q<__receiver_, _ReceiverId, _Fun, _Let>>>>;
-template <class _SenderId, class _ReceiverId, class _FunId, class _Let>
-using __operation_base = typename __receiver<_SenderId, _ReceiverId, _FunId,
- _Let>::__operation_base_t;
+template <class _SenderId, class _ReceiverId, class _Fun, class _Let>
+using __operation_base =
+ typename __receiver<_SenderId, _ReceiverId, _Fun, _Let>::__operation_base_t;
-template <class _SenderId, class _ReceiverId, class _FunId, class _Let>
-struct __operation : __operation_base<_SenderId, _ReceiverId, _FunId, _Let>
+template <class _SenderId, class _ReceiverId, class _Fun, class _Let>
+struct __operation
{
- using _Sender = __t<_SenderId>;
- using _Fun = __t<_FunId>;
- using __op_base_t = __operation_base<_SenderId, _ReceiverId, _FunId, _Let>;
- using __receiver_t = __receiver<_SenderId, _ReceiverId, _FunId, _Let>;
+ using _Sender = stdexec::__t<_SenderId>;
- friend void tag_invoke(start_t, __operation& __self) noexcept
+ struct __t : __operation_base<_SenderId, _ReceiverId, _Fun, _Let>
{
- start(__self.__op_state2_);
- }
+ using __id = __operation;
+ using __op_base_t =
+ __operation_base<_SenderId, _ReceiverId, _Fun, _Let>;
+ using __receiver_t = __receiver<_SenderId, _ReceiverId, _Fun, _Let>;
- template <class _Receiver2>
- __operation(_Sender&& __sndr, _Receiver2&& __rcvr, _Fun __fun) :
- __op_base_t{{}, (_Receiver2 &&) __rcvr, (_Fun &&) __fun},
- __op_state2_(connect((_Sender &&) __sndr, __receiver_t{this}))
- {}
+ friend void tag_invoke(start_t, __t& __self) noexcept
+ {
+ start(__self.__op_state2_);
+ }
- connect_result_t<_Sender, __receiver_t> __op_state2_;
+ template <class _Receiver2>
+ __t(_Sender&& __sndr, _Receiver2&& __rcvr, _Fun __fun) :
+ __op_base_t{{}, (_Receiver2 &&) __rcvr, (_Fun &&) __fun},
+ __op_state2_(connect((_Sender &&) __sndr, __receiver_t{this}))
+ {}
+
+ connect_result_t<_Sender, __receiver_t> __op_state2_;
+ };
};
-template <class _SenderId, class _FunId, class _SetId>
+template <class _SenderId, class _Fun, class _SetId>
struct __sender
{
- using _Sender = __t<_SenderId>;
- using _Fun = __t<_FunId>;
- using _Set = __t<_SetId>;
- template <class _Self, class _Receiver>
- using __operation_t =
- __operation<__x<__member_t<_Self, _Sender>>,
- __x<remove_cvref_t<_Receiver>>, _FunId, _Set>;
- template <class _Self, class _Receiver>
- using __receiver_t =
- __receiver<__x<__member_t<_Self, _Sender>>,
- __x<remove_cvref_t<_Receiver>>, _FunId, _Set>;
+ using _Sender = stdexec::__t<_SenderId>;
+ using _Set = stdexec::__t<_SetId>;
- template <class _Sender, class _Env>
- using __completions =
- __mapply<__transform<__mbind_front_q1<__tfx_signal_t, _Env, _Fun, _Set>,
- __q<__concat_completion_signatures_t>>,
- completion_signatures_of_t<_Sender, _Env>>;
-
- template <__decays_to<__sender> _Self, receiver _Receiver>
- requires sender_to<__member_t<_Self, _Sender>,
- __receiver_t<_Self, _Receiver>>
- friend auto tag_invoke(connect_t, _Self&& __self, _Receiver&& __rcvr)
- -> __operation_t<_Self, _Receiver>
+ struct __t
{
- return __operation_t<_Self, _Receiver>{((_Self &&) __self).__sndr_,
- (_Receiver &&) __rcvr,
- ((_Self &&) __self).__fun_};
- }
+ using __id = __sender;
- template <tag_category<forwarding_sender_query> _Tag, class... _As>
- requires __callable<_Tag, const _Sender&, _As...>
- friend auto
- tag_invoke(_Tag __tag, const __sender& __self, _As&&... __as) noexcept(
- __nothrow_callable<_Tag, const _Sender&, _As...>)
+ template <class _Self, class _Receiver>
+ using __operation_t = stdexec::__t<
+ __operation<stdexec::__id<__copy_cvref_t<_Self, _Sender>>,
+ stdexec::__id<_Receiver>, _Fun, _Set>>;
+ template <class _Self, class _Receiver>
+ using __receiver_t =
+ __receiver<stdexec::__id<__copy_cvref_t<_Self, _Sender>>,
+ stdexec::__id<_Receiver>, _Fun, _Set>;
+
+ template <class _Sender, class _Env>
+ using __completions = __mapply<
+ __transform<__mbind_front_q<__tfx_signal_t, _Env, _Fun, _Set>,
+ __q<__concat_completion_signatures_t>>,
+ completion_signatures_of_t<_Sender, _Env>>;
+
+ template <__decays_to<__t> _Self, receiver _Receiver>
+ requires sender_to<__copy_cvref_t<_Self, _Sender>,
+ __receiver_t<_Self, _Receiver>>
+ friend auto tag_invoke(connect_t, _Self&& __self, _Receiver __rcvr)
+ -> __operation_t<_Self, _Receiver>
+ {
+ return __operation_t<_Self, _Receiver>{((_Self &&) __self).__sndr_,
+ (_Receiver &&) __rcvr,
+ ((_Self &&) __self).__fun_};
+ }
+
+ template <tag_category<forwarding_sender_query> _Tag, class... _As>
+ requires __callable<_Tag, const _Sender&, _As...>
+ friend auto tag_invoke(
+ _Tag __tag, const __t& __self,
+ _As&&... __as) noexcept(__nothrow_callable<_Tag, const _Sender&,
+ _As...>)
-> __call_result_if_t<tag_category<_Tag, forwarding_sender_query>,
_Tag, const _Sender&, _As...>
- {
- return ((_Tag &&) __tag)(__self.__sndr_, (_As &&) __as...);
- }
+ {
+ return ((_Tag &&) __tag)(__self.__sndr_, (_As &&) __as...);
+ }
- template <__decays_to<__sender> _Self, class _Env>
- friend auto tag_invoke(get_completion_signatures_t, _Self&&, _Env)
- -> dependent_completion_signatures<_Env>;
- template <__decays_to<__sender> _Self, class _Env>
- friend auto tag_invoke(get_completion_signatures_t, _Self&&, _Env)
- -> __completions<__member_t<_Self, _Sender>, _Env>
- requires true;
+ template <__decays_to<__t> _Self, class _Env>
+ friend auto tag_invoke(get_completion_signatures_t, _Self&&, _Env)
+ -> dependent_completion_signatures<_Env>;
+ template <__decays_to<__t> _Self, class _Env>
+ friend auto tag_invoke(get_completion_signatures_t, _Self&&, _Env)
+ -> __completions<__copy_cvref_t<_Self, _Sender>, _Env>
+ requires true;
- _Sender __sndr_;
- _Fun __fun_;
+ _Sender __sndr_;
+ _Fun __fun_;
+ };
};
template <class _LetTag, class _SetTag>
@@ -4298,8 +4316,8 @@
{
using __t = _SetTag;
template <class _Sender, class _Fun>
- using __sender = __let::__sender<__x<remove_cvref_t<_Sender>>,
- __x<remove_cvref_t<_Fun>>, _LetTag>;
+ using __sender = stdexec::__t<
+ __let::__sender<stdexec::__id<remove_cvref_t<_Sender>>, _Fun, _LetTag>>;
template <sender _Sender, __movable_value _Fun>
requires __tag_invocable_with_completion_scheduler<_LetTag, set_value_t,
@@ -4363,121 +4381,143 @@
struct __operation;
template <class _SenderId, class _ReceiverId>
-struct __receiver : receiver_adaptor<__receiver<_SenderId, _ReceiverId>>
+struct __receiver
{
using _Sender = stdexec::__t<_SenderId>;
using _Receiver = stdexec::__t<_ReceiverId>;
- _Receiver&& base() && noexcept
- {
- return (_Receiver &&) __op_->__rcvr_;
- }
- const _Receiver& base() const& noexcept
- {
- return __op_->__rcvr_;
- }
- template <class _Ty>
- void set_value(_Ty&& __a) && noexcept
- try
+ struct __t : receiver_adaptor<__t>
{
- using _Value = __single_sender_value_t<_Sender, env_of_t<_Receiver>>;
- static_assert(constructible_from<_Value, _Ty>);
- stdexec::set_value(((__receiver &&) * this).base(),
- std::optional<_Value>{(_Ty &&) __a});
- }
- catch (...)
- {
- stdexec::set_error(((__receiver &&) * this).base(),
- std::current_exception());
- }
- void set_stopped() && noexcept
- {
- using _Value = __single_sender_value_t<_Sender, env_of_t<_Receiver>>;
- stdexec::set_value(((__receiver &&) * this).base(),
- std::optional<_Value>{std::nullopt});
- }
+ using __id = __receiver;
- __operation<_SenderId, _ReceiverId>* __op_;
+ _Receiver&& base() && noexcept
+ {
+ return (_Receiver &&) __op_->__rcvr_;
+ }
+ const _Receiver& base() const& noexcept
+ {
+ return __op_->__rcvr_;
+ }
+
+ template <class _Ty>
+ void set_value(_Ty&& __a) && noexcept
+ try
+ {
+ using _Value =
+ __single_sender_value_t<_Sender, env_of_t<_Receiver>>;
+ static_assert(constructible_from<_Value, _Ty>);
+ stdexec::set_value(((__t &&) * this).base(),
+ std::optional<_Value>{(_Ty &&) __a});
+ }
+ catch (...)
+ {
+ stdexec::set_error(((__t &&) * this).base(),
+ std::current_exception());
+ }
+ void set_stopped() && noexcept
+ {
+ using _Value =
+ __single_sender_value_t<_Sender, env_of_t<_Receiver>>;
+ stdexec::set_value(((__t &&) * this).base(),
+ std::optional<_Value>{std::nullopt});
+ }
+
+ stdexec::__t<__operation<_SenderId, _ReceiverId>>* __op_;
+ };
};
template <class _SenderId, class _ReceiverId>
struct __operation
{
- using _Sender = __t<_SenderId>;
- using _Receiver = __t<_ReceiverId>;
- using __receiver_t = __receiver<_SenderId, _ReceiverId>;
+ using _Sender = stdexec::__t<_SenderId>;
+ using _Receiver = stdexec::__t<_ReceiverId>;
+ using __receiver_t = stdexec::__t<__receiver<_SenderId, _ReceiverId>>;
- __operation(_Sender&& __sndr, _Receiver&& __rcvr) :
- __rcvr_((_Receiver &&) __rcvr),
- __op_state_(connect((_Sender &&) __sndr, __receiver_t{{}, this}))
- {}
- STDEXEC_IMMOVABLE(__operation);
-
- friend void tag_invoke(start_t, __operation& __self) noexcept
+ struct __t
{
- start(__self.__op_state_);
- }
+ using __id = __operation;
+ __t(_Sender&& __sndr, _Receiver&& __rcvr) :
+ __rcvr_((_Receiver &&) __rcvr),
+ __op_state_(connect((_Sender &&) __sndr, __receiver_t{{}, this}))
+ {}
+ STDEXEC_IMMOVABLE(__t);
- _Receiver __rcvr_;
- connect_result_t<_Sender, __receiver_t> __op_state_;
+ friend void tag_invoke(start_t, __t& __self) noexcept
+ {
+ start(__self.__op_state_);
+ }
+
+ _Receiver __rcvr_;
+ connect_result_t<_Sender, __receiver_t> __op_state_;
+ };
};
template <class _SenderId>
struct __sender
{
- using _Sender = __t<_SenderId>;
- template <class _Self, class _Receiver>
- using __operation_t =
- __operation<__x<__member_t<_Self, _Sender>>, __x<decay_t<_Receiver>>>;
- template <class _Self, class _Receiver>
- using __receiver_t =
- __receiver<__x<__member_t<_Self, _Sender>>, __x<decay_t<_Receiver>>>;
+ using _Sender = stdexec::__t<_SenderId>;
- template <__decays_to<__sender> _Self, receiver _Receiver>
- requires __single_typed_sender<__member_t<_Self, _Sender>,
- env_of_t<_Receiver>> &&
- sender_to<__member_t<_Self, _Sender>,
- __receiver_t<_Self, _Receiver>>
- friend auto tag_invoke(connect_t, _Self&& __self,
- _Receiver&& __rcvr)
- -> __operation_t<_Self, _Receiver>
+ struct __t
{
- return {((_Self &&) __self).__sndr_, (_Receiver &&) __rcvr};
- }
+ using __id = __sender;
- template <tag_category<forwarding_sender_query> _Tag, class... _As>
- requires __callable<_Tag, const _Sender&, _As...>
- friend auto
- tag_invoke(_Tag __tag, const __sender& __self, _As&&... __as) noexcept(
- __nothrow_callable<_Tag, const _Sender&, _As...>)
+ template <class _Self, class _Receiver>
+ using __operation_t = stdexec::__t<
+ __operation<stdexec::__id<__copy_cvref_t<_Self, _Sender>>,
+ stdexec::__id<_Receiver>>>;
+ template <class _Self, class _Receiver>
+ using __receiver_t = stdexec::__t<
+ __receiver<stdexec::__id<__copy_cvref_t<_Self, _Sender>>,
+ stdexec::__id<_Receiver>>>;
+
+ template <__decays_to<__t> _Self, receiver _Receiver>
+ requires __single_typed_sender<__copy_cvref_t<_Self, _Sender>,
+ env_of_t<_Receiver>> &&
+ sender_to<__copy_cvref_t<_Self, _Sender>,
+ __receiver_t<_Self, _Receiver>>
+ friend auto tag_invoke(connect_t, _Self&& __self,
+ _Receiver __rcvr)
+ -> __operation_t<_Self, _Receiver>
+ {
+ return {((_Self &&) __self).__sndr_, (_Receiver &&) __rcvr};
+ }
+
+ template <tag_category<forwarding_sender_query> _Tag, class... _As>
+ requires __callable<_Tag, const _Sender&, _As...>
+ friend auto tag_invoke(
+ _Tag __tag, const __t& __self,
+ _As&&... __as) noexcept(__nothrow_callable<_Tag, const _Sender&,
+ _As...>)
-> __call_result_if_t<tag_category<_Tag, forwarding_sender_query>,
_Tag, const _Sender&, _As...>
- {
- return ((_Tag &&) __tag)(__self.__sndr_, (_As &&) __as...);
- }
+ {
+ return ((_Tag &&) __tag)(__self.__sndr_, (_As &&) __as...);
+ }
- template <class... _Tys>
- requires(sizeof...(_Tys) == 1)
- using __set_value_t =
- completion_signatures<set_value_t(std::optional<_Tys>...)>;
+ template <class... _Tys>
+ requires(sizeof...(_Tys) == 1)
+ using __set_value_t =
+ completion_signatures<set_value_t(std::optional<_Tys>...)>;
- template <class _Ty>
- using __set_error_t = completion_signatures<set_error_t(_Ty)>;
+ template <class _Ty>
+ using __set_error_t = completion_signatures<set_error_t(_Ty)>;
- template <__decays_to<__sender> _Self, class _Env>
- friend auto tag_invoke(get_completion_signatures_t, _Self&&, _Env)
- -> make_completion_signatures<
- __member_t<_Self, _Sender>, _Env,
- completion_signatures<set_error_t(std::exception_ptr)>,
- __set_value_t, __set_error_t, completion_signatures<>>;
+ template <__decays_to<__t> _Self, class _Env>
+ friend auto tag_invoke(get_completion_signatures_t, _Self&&, _Env)
+ -> make_completion_signatures<
+ __copy_cvref_t<_Self, _Sender>, _Env,
+ completion_signatures<set_error_t(std::exception_ptr)>,
+ __set_value_t, __set_error_t, completion_signatures<>>;
- _Sender __sndr_;
+ _Sender __sndr_;
+ };
};
struct stopped_as_optional_t
{
template <sender _Sender>
- auto operator()(_Sender&& __sndr) const -> __sender<__x<decay_t<_Sender>>>
+ auto operator()(_Sender&& __sndr) const
+ -> __t<__sender<stdexec::__id<decay_t<_Sender>>>>
{
return {(_Sender &&) __sndr};
}
@@ -4517,8 +4557,6 @@
{
class run_loop;
-namespace __impl
-{
struct __task : __immovable
{
__task* __next_ = this;
@@ -4535,46 +4573,51 @@
};
template <class _ReceiverId>
-struct __operation : __task
+struct __operation
{
- using _Receiver = __t<_ReceiverId>;
- run_loop* __loop_;
- [[no_unique_address]] _Receiver __rcvr_;
+ using _Receiver = stdexec::__t<_ReceiverId>;
- static void __execute_impl(__task* __p) noexcept
+ struct __t : __task
{
- auto& __rcvr = ((__operation*)__p)->__rcvr_;
- try
+ using __id = __operation;
+
+ run_loop* __loop_;
+ [[no_unique_address]] _Receiver __rcvr_;
+
+ static void __execute_impl(__task* __p) noexcept
{
- if (get_stop_token(get_env(__rcvr)).stop_requested())
+ auto& __rcvr = ((__t*)__p)->__rcvr_;
+ try
{
- set_stopped((_Receiver &&) __rcvr);
+ if (get_stop_token(get_env(__rcvr)).stop_requested())
+ {
+ set_stopped((_Receiver &&) __rcvr);
+ }
+ else
+ {
+ set_value((_Receiver &&) __rcvr);
+ }
}
- else
+ catch (...)
{
- set_value((_Receiver &&) __rcvr);
+ set_error((_Receiver &&) __rcvr, std::current_exception());
}
}
- catch (...)
+
+ explicit __t(__task* __tail) noexcept : __task{.__tail_ = __tail} {}
+ __t(__task* __next, run_loop* __loop, _Receiver __rcvr) :
+ __task{{}, __next, {&__execute_impl}}, __loop_{__loop},
+ __rcvr_{(_Receiver &&) __rcvr}
+ {}
+
+ friend void tag_invoke(start_t, __t& __self) noexcept
{
- set_error((_Receiver &&) __rcvr, std::current_exception());
+ __self.__start_();
}
- }
- explicit __operation(__task* __tail) noexcept : __task{.__tail_ = __tail} {}
- __operation(__task* __next, run_loop* __loop, _Receiver __rcvr) :
- __task{{}, __next, {&__execute_impl}}, __loop_{__loop},
- __rcvr_{(_Receiver &&) __rcvr}
- {}
-
- friend void tag_invoke(start_t, __operation& __self) noexcept
- {
- __self.__start_();
- }
-
- void __start_() noexcept;
+ void __start_() noexcept;
+ };
};
-} // namespace __impl
class run_loop
{
@@ -4582,13 +4625,20 @@
using __completion_signatures_ = completion_signatures<Ts...>;
template <class>
- friend struct __impl::__operation;
+ friend struct __operation;
public:
- class __scheduler
+ struct __scheduler
{
+ using __t = __scheduler;
+ using __id = __scheduler;
+ bool operator==(const __scheduler&) const noexcept = default;
+
+ private:
struct __schedule_task
{
+ using __t = __schedule_task;
+ using __id = __schedule_task;
using completion_signatures =
__completion_signatures_<set_value_t(),
set_error_t(std::exception_ptr),
@@ -4598,12 +4648,13 @@
friend __scheduler;
template <class _Receiver>
- using __operation = __impl::__operation<__x<decay_t<_Receiver>>>;
+ using __operation =
+ stdexec::__t<__operation<stdexec::__id<_Receiver>>>;
template <class _Receiver>
friend __operation<_Receiver>
tag_invoke(connect_t, const __schedule_task& __self,
- _Receiver&& __rcvr)
+ _Receiver __rcvr)
{
return __self.__connect_((_Receiver &&) __rcvr);
}
@@ -4633,7 +4684,6 @@
explicit __scheduler(run_loop* __loop) noexcept : __loop_(__loop) {}
- public:
friend __schedule_task tag_invoke(schedule_t,
const __scheduler& __self) noexcept
{
@@ -4654,9 +4704,6 @@
return false;
}
- bool operator==(const __scheduler&) const noexcept = default;
-
- private:
__schedule_task __schedule() const noexcept
{
return __schedule_task{__loop_};
@@ -4674,19 +4721,17 @@
void finish();
private:
- void __push_back_(__impl::__task* __task);
- __impl::__task* __pop_front_();
+ void __push_back_(__task* __task);
+ __task* __pop_front_();
std::mutex __mutex_;
std::condition_variable __cv_;
- __impl::__task __head_{.__tail_ = &__head_};
+ __task __head_{.__tail_ = &__head_};
bool __stop_ = false;
};
-namespace __impl
-{
template <class _ReceiverId>
-inline void __operation<_ReceiverId>::__start_() noexcept
+inline void __operation<_ReceiverId>::__t::__start_() noexcept
try
{
__loop_->__push_back_(this);
@@ -4695,11 +4740,10 @@
{
set_error((_Receiver &&) __rcvr_, std::current_exception());
}
-} // namespace __impl
inline void run_loop::run()
{
- for (__impl::__task* __task; (__task = __pop_front_()) != &__head_;)
+ for (__task* __task; (__task = __pop_front_()) != &__head_;)
{
__task->__execute();
}
@@ -4712,7 +4756,7 @@
__cv_.notify_all();
}
-inline void run_loop::__push_back_(__impl::__task* __task)
+inline void run_loop::__push_back_(__task* __task)
{
std::unique_lock __lock{__mutex_};
__task->__next_ = &__head_;
@@ -4720,7 +4764,7 @@
__cv_.notify_one();
}
-inline __impl::__task* run_loop::__pop_front_()
+inline __task* run_loop::__pop_front_()
{
std::unique_lock __lock{__mutex_};
__cv_.wait(__lock,
@@ -4761,12 +4805,13 @@
template <class _Sender, class _Env, class _State, class _Tag>
using __bind_completions_t =
- __gather_sigs_t<_Tag, _Sender, _Env, __tuple_t<_Tag>, __make_bind<_State>>;
+ __gather_completions_for<_Tag, _Sender, _Env, __tuple_t<_Tag>,
+ __make_bind<_State>>;
template <class _Sender, class _Env>
using __variant_for_t = __minvoke<__minvoke<
- __fold_right<__nullable_variant_t,
- __mbind_front_q2<__bind_completions_t, _Sender, _Env>>,
+ __mfold_right<__nullable_variant_t,
+ __mbind_front_q<__bind_completions_t, _Sender, _Env>>,
set_value_t, set_error_t, set_stopped_t>>;
template <class _SchedulerId, class _CvrefSenderId, class _ReceiverId>
@@ -4785,29 +4830,36 @@
template <class _SchedulerId, class _CvrefSenderId, class _ReceiverId>
struct __receiver2
{
- using _Receiver = __t<_ReceiverId>;
- __operation1<_SchedulerId, _CvrefSenderId, _ReceiverId>* __op_state_;
+ using _Receiver = stdexec::__t<_ReceiverId>;
- // If the work is successfully scheduled on the new execution
- // context and is ready to run, forward the completion signal in
- // the operation state
- friend void tag_invoke(set_value_t, __receiver2&& __self) noexcept
+ struct __t
{
- __self.__op_state_->__complete();
- }
+ using __id = __receiver2;
+ stdexec::__t<__operation1<_SchedulerId, _CvrefSenderId, _ReceiverId>>*
+ __op_state_;
- template <__one_of<set_error_t, set_stopped_t> _Tag, class... _As>
- requires __callable<_Tag, _Receiver, _As...>
- friend void tag_invoke(_Tag, __receiver2&& __self, _As&&... __as) noexcept
- {
- _Tag{}((_Receiver &&) __self.__op_state_->__rcvr_, (_As &&) __as...);
- }
+ // If the work is successfully scheduled on the new execution
+ // context and is ready to run, forward the completion signal in
+ // the operation state
+ friend void tag_invoke(set_value_t, __t&& __self) noexcept
+ {
+ __self.__op_state_->__complete();
+ }
- friend auto tag_invoke(get_env_t, const __receiver2& __self)
- -> env_of_t<_Receiver>
- {
- return get_env(__self.__op_state_->__rcvr_);
- }
+ template <__one_of<set_error_t, set_stopped_t> _Tag, class... _As>
+ requires __callable<_Tag, _Receiver, _As...>
+ friend void tag_invoke(_Tag, __t&& __self, _As&&... __as) noexcept
+ {
+ _Tag{}((_Receiver &&) __self.__op_state_->__rcvr_,
+ (_As &&) __as...);
+ }
+
+ friend auto tag_invoke(get_env_t, const __t& __self)
+ -> env_of_t<_Receiver>
+ {
+ return get_env(__self.__op_state_->__rcvr_);
+ }
+ };
};
// This receiver is connected to the input sender. When that
@@ -4820,174 +4872,190 @@
template <class _SchedulerId, class _CvrefSenderId, class _ReceiverId>
struct __receiver1
{
- using _Scheduler = __t<_SchedulerId>;
- using _CvrefSender = __t<_CvrefSenderId>;
- using _Receiver = __t<_ReceiverId>;
+ using _Scheduler = stdexec::__t<_SchedulerId>;
+ using _CvrefSender = stdexec::__t<_CvrefSenderId>;
+ using _Receiver = stdexec::__t<_ReceiverId>;
using __receiver2_t =
- __receiver2<_SchedulerId, _CvrefSenderId, _ReceiverId>;
- __operation1<_SchedulerId, _CvrefSenderId, _ReceiverId>* __op_state_;
+ stdexec::__t<__receiver2<_SchedulerId, _CvrefSenderId, _ReceiverId>>;
- template <class... _Args>
- static constexpr bool __nothrow_complete_ =
- (__nothrow_decay_copyable<_Args> && ...);
-
- template <class _Tag, class... _Args>
- static void
- __complete_(_Tag __tag, __receiver1&& __self,
- _Args&&... __args) noexcept(__nothrow_complete_<_Args...>)
+ struct __t
{
- // Write the tag and the args into the operation state so that
- // we can forward the completion from within the scheduler's
- // execution context.
- __self.__op_state_->__data_
- .template emplace<__decayed_tuple<_Tag, _Args...>>(
- _Tag{}, (_Args &&) __args...);
- // Enqueue the schedule operation so the completion happens
- // on the scheduler's execution context.
- start(__self.__op_state_->__state2_);
- }
+ stdexec::__t<__operation1<_SchedulerId, _CvrefSenderId, _ReceiverId>>*
+ __op_state_;
- template <__one_of<set_value_t, set_error_t, set_stopped_t> _Tag,
- class... _Args>
- requires __callable<_Tag, _Receiver, _Args...>
- friend void tag_invoke(_Tag __tag, __receiver1&& __self,
- _Args&&... __args) noexcept
- {
- __try_call((_Receiver &&) __self.__op_state_->__rcvr_,
- __fun_c<__complete_<_Tag, _Args...>>, (_Tag &&) __tag,
- (__receiver1 &&) __self, (_Args &&) __args...);
- }
+ template <class... _Args>
+ static constexpr bool __nothrow_complete_ =
+ (__nothrow_decay_copyable<_Args> && ...);
- friend auto tag_invoke(get_env_t, const __receiver1& __self)
- -> env_of_t<_Receiver>
- {
- return get_env(__self.__op_state_->__rcvr_);
- }
+ template <class _Tag, class... _Args>
+ static void __complete_(
+ _Tag __tag, __t&& __self,
+ _Args&&... __args) noexcept(__nothrow_complete_<_Args...>)
+ {
+ // Write the tag and the args into the operation state so that
+ // we can forward the completion from within the scheduler's
+ // execution context.
+ __self.__op_state_->__data_
+ .template emplace<__decayed_tuple<_Tag, _Args...>>(
+ _Tag{}, (_Args &&) __args...);
+ // Enqueue the schedule operation so the completion happens
+ // on the scheduler's execution context.
+ start(__self.__op_state_->__state2_);
+ }
+
+ template <__one_of<set_value_t, set_error_t, set_stopped_t> _Tag,
+ class... _Args>
+ requires __callable<_Tag, _Receiver, _Args...>
+ friend void tag_invoke(_Tag __tag, __t&& __self,
+ _Args&&... __args) noexcept
+ {
+ __try_call((_Receiver &&) __self.__op_state_->__rcvr_,
+ __fun_c<__complete_<_Tag, _Args...>>, (_Tag &&) __tag,
+ (__t &&) __self, (_Args &&) __args...);
+ }
+
+ friend auto tag_invoke(get_env_t, const __t& __self)
+ -> env_of_t<_Receiver>
+ {
+ return get_env(__self.__op_state_->__rcvr_);
+ }
+ };
};
template <class _SchedulerId, class _CvrefSenderId, class _ReceiverId>
struct __operation1
{
- using _Scheduler = __t<_SchedulerId>;
- using _CvrefSender = __t<_CvrefSenderId>;
- using _Receiver = __t<_ReceiverId>;
+ using _Scheduler = stdexec::__t<_SchedulerId>;
+ using _CvrefSender = stdexec::__t<_CvrefSenderId>;
+ using _Receiver = stdexec::__t<_ReceiverId>;
using __receiver1_t =
- __receiver1<_SchedulerId, _CvrefSenderId, _ReceiverId>;
+ stdexec::__t<__receiver1<_SchedulerId, _CvrefSenderId, _ReceiverId>>;
using __receiver2_t =
- __receiver2<_SchedulerId, _CvrefSenderId, _ReceiverId>;
+ stdexec::__t<__receiver2<_SchedulerId, _CvrefSenderId, _ReceiverId>>;
using __variant_t = __variant_for_t<_CvrefSender, env_of_t<_Receiver>>;
- _Scheduler __sched_;
- _Receiver __rcvr_;
- __variant_t __data_;
- connect_result_t<_CvrefSender, __receiver1_t> __state1_;
- connect_result_t<schedule_result_t<_Scheduler>, __receiver2_t> __state2_;
-
- template <__decays_to<_Receiver> _CvrefReceiver>
- __operation1(_Scheduler __sched, _CvrefSender&& __sndr,
- _CvrefReceiver&& __rcvr) :
- __sched_((_Scheduler &&) __sched),
- __rcvr_((_CvrefReceiver &&) __rcvr),
- __state1_(connect((_CvrefSender &&) __sndr, __receiver1_t{this})),
- __state2_(connect(schedule(__sched_), __receiver2_t{this}))
- {}
- STDEXEC_IMMOVABLE(__operation1);
-
- friend void tag_invoke(start_t, __operation1& __op_state) noexcept
+ struct __t
{
- start(__op_state.__state1_);
- }
+ using __id = __operation1;
+ _Scheduler __sched_;
+ _Receiver __rcvr_;
+ __variant_t __data_;
+ connect_result_t<_CvrefSender, __receiver1_t> __state1_;
+ connect_result_t<schedule_result_t<_Scheduler>, __receiver2_t>
+ __state2_;
- void __complete() noexcept
- try
- {
- std::visit(
- [&]<class _Tup>(_Tup& __tupl) -> void {
- if constexpr (same_as<_Tup, std::monostate>)
- {
- std::terminate(); // reaching this indicates a bug in
- // schedule_from
- }
- else
- {
- std::apply(
- [&]<class... _Args>(auto __tag,
- _Args&... __args) -> void {
- __tag((_Receiver &&) __rcvr_, (_Args &&) __args...);
- },
- __tupl);
- }
- },
- __data_);
- }
- catch (...)
- {
- set_error((_Receiver &&) __rcvr_, std::current_exception());
- }
+ __t(_Scheduler __sched, _CvrefSender&& __sndr, _Receiver&& __rcvr) :
+ __sched_((_Scheduler &&) __sched), __rcvr_((_Receiver &&) __rcvr),
+ __state1_(connect((_CvrefSender &&) __sndr, __receiver1_t{this})),
+ __state2_(connect(schedule(__sched_), __receiver2_t{this}))
+ {}
+ STDEXEC_IMMOVABLE(__t);
+
+ friend void tag_invoke(start_t, __t& __op_state) noexcept
+ {
+ start(__op_state.__state1_);
+ }
+
+ void __complete() noexcept
+ try
+ {
+ std::visit(
+ [&]<class _Tup>(_Tup& __tupl) -> void {
+ if constexpr (same_as<_Tup, std::monostate>)
+ {
+ std::terminate(); // reaching this indicates a bug in
+ // schedule_from
+ }
+ else
+ {
+ std::apply(
+ [&]<class... _Args>(auto __tag,
+ _Args&... __args) -> void {
+ __tag((_Receiver &&) __rcvr_,
+ (_Args &&) __args...);
+ },
+ __tupl);
+ }
+ },
+ __data_);
+ }
+ catch (...)
+ {
+ set_error((_Receiver &&) __rcvr_, std::current_exception());
+ }
+ };
};
template <class _Tag>
using __decay_signature =
- __transform<__q1<decay_t>,
- __mcompose<__q1<completion_signatures>, __qf<_Tag>>>;
+ __transform<__q<decay_t>,
+ __mcompose<__q<completion_signatures>, __qf<_Tag>>>;
template <class _SchedulerId, class _SenderId>
struct __sender
{
- using _Scheduler = __t<_SchedulerId>;
- using _Sender = __t<_SenderId>;
- _Scheduler __sched_;
- _Sender __sndr_;
+ using _Scheduler = stdexec::__t<_SchedulerId>;
+ using _Sender = stdexec::__t<_SenderId>;
- template <__decays_to<__sender> _Self, class _Receiver>
- requires sender_to<__member_t<_Self, _Sender>, _Receiver>
- friend auto tag_invoke(connect_t, _Self&& __self, _Receiver&& __rcvr)
- -> __operation1<_SchedulerId, __x<__member_t<_Self, _Sender>>,
- __x<decay_t<_Receiver>>>
+ struct __t
{
- return {__self.__sched_, ((_Self &&) __self).__sndr_,
- (_Receiver &&) __rcvr};
- }
+ using __id = __sender;
+ _Scheduler __sched_;
+ _Sender __sndr_;
- template <__one_of<set_value_t, set_stopped_t> _Tag>
- friend _Scheduler tag_invoke(get_completion_scheduler_t<_Tag>,
- const __sender& __self) noexcept
- {
- return __self.__sched_;
- }
+ template <__decays_to<__t> _Self, class _Receiver>
+ requires sender_to<__copy_cvref_t<_Self, _Sender>, _Receiver>
+ friend auto tag_invoke(connect_t, _Self&& __self, _Receiver __rcvr)
+ -> stdexec::__t<__operation1<
+ _SchedulerId, stdexec::__id<__copy_cvref_t<_Self, _Sender>>,
+ stdexec::__id<_Receiver>>>
+ {
+ return {__self.__sched_, ((_Self &&) __self).__sndr_,
+ (_Receiver &&) __rcvr};
+ }
- template <tag_category<forwarding_sender_query> _Tag, class... _As>
- requires __callable<_Tag, const _Sender&, _As...>
- friend auto
- tag_invoke(_Tag __tag, const __sender& __self, _As&&... __as) noexcept(
- __nothrow_callable<_Tag, const _Sender&, _As...>)
+ template <__one_of<set_value_t, set_stopped_t> _Tag>
+ friend _Scheduler tag_invoke(get_completion_scheduler_t<_Tag>,
+ const __t& __self) noexcept
+ {
+ return __self.__sched_;
+ }
+
+ template <tag_category<forwarding_sender_query> _Tag, class... _As>
+ requires __callable<_Tag, const _Sender&, _As...>
+ friend auto tag_invoke(
+ _Tag __tag, const __t& __self,
+ _As&&... __as) noexcept(__nothrow_callable<_Tag, const _Sender&,
+ _As...>)
-> __call_result_if_t<tag_category<_Tag, forwarding_sender_query>,
_Tag, const _Sender&, _As...>
- {
- return ((_Tag &&) __tag)(__self.__sndr_, (_As &&) __as...);
- }
+ {
+ return ((_Tag &&) __tag)(__self.__sndr_, (_As &&) __as...);
+ }
- template <class... _Errs>
- using __all_nothrow_decay_copyable =
- __bool<(__nothrow_decay_copyable<_Errs> && ...)>;
+ template <class... _Errs>
+ using __all_nothrow_decay_copyable =
+ __bool<(__nothrow_decay_copyable<_Errs> && ...)>;
- template <class _Env>
- using __with_error_t =
- __if_c<__v<error_types_of_t<schedule_result_t<_Scheduler>, _Env,
- __all_nothrow_decay_copyable>>,
- completion_signatures<>, __with_exception_ptr>;
+ template <class _Env>
+ using __with_error_t =
+ __if_c<__v<error_types_of_t<schedule_result_t<_Scheduler>, _Env,
+ __all_nothrow_decay_copyable>>,
+ completion_signatures<>, __with_exception_ptr>;
- template <class _Env>
- using __scheduler_completions_t =
- __make_completion_signatures<schedule_result_t<_Scheduler>, _Env,
- __with_error_t<_Env>,
- __mconst<completion_signatures<>>>;
+ template <class _Env>
+ using __scheduler_completions_t =
+ __make_completion_signatures<schedule_result_t<_Scheduler>, _Env,
+ __with_error_t<_Env>,
+ __mconst<completion_signatures<>>>;
- template <__decays_to<__sender> _Self, class _Env>
- friend auto tag_invoke(get_completion_signatures_t, _Self&&, _Env)
- -> __make_completion_signatures<
- __member_t<_Self, _Sender>, _Env, __scheduler_completions_t<_Env>,
- __decay_signature<set_value_t>, __decay_signature<set_error_t>>;
+ template <__decays_to<__t> _Self, class _Env>
+ friend auto tag_invoke(get_completion_signatures_t, _Self&&, _Env)
+ -> __make_completion_signatures<
+ __copy_cvref_t<_Self, _Sender>, _Env,
+ __scheduler_completions_t<_Env>, __decay_signature<set_value_t>,
+ __decay_signature<set_error_t>>;
+ };
};
struct schedule_from_t
@@ -5003,7 +5071,8 @@
template <scheduler _Scheduler, sender _Sender>
auto operator()(_Scheduler&& __sched, _Sender&& __sndr) const
- -> __sender<__x<decay_t<_Scheduler>>, __x<decay_t<_Sender>>>
+ -> stdexec::__t<__sender<stdexec::__id<decay_t<_Scheduler>>,
+ stdexec::__id<decay_t<_Sender>>>>
{
return {(_Scheduler &&) __sched, (_Sender &&) __sndr};
}
@@ -5068,161 +5137,189 @@
// [execution.senders.adaptors.on]
namespace __on
{
-namespace __impl
-{
template <class _SchedulerId, class _SenderId, class _ReceiverId>
struct __operation;
template <class _SchedulerId, class _SenderId, class _ReceiverId>
-struct __receiver_ref :
- receiver_adaptor<__receiver_ref<_SchedulerId, _SenderId, _ReceiverId>>
+struct __receiver_ref
{
using _Scheduler = stdexec::__t<_SchedulerId>;
using _Sender = stdexec::__t<_SenderId>;
using _Receiver = stdexec::__t<_ReceiverId>;
- __operation<_SchedulerId, _SenderId, _ReceiverId>* __op_state_;
- _Receiver&& base() && noexcept
+
+ struct __t : receiver_adaptor<__t>
{
- return (_Receiver &&) __op_state_->__rcvr_;
- }
- const _Receiver& base() const& noexcept
- {
- return __op_state_->__rcvr_;
- }
- auto get_env() const -> __make_env_t<env_of_t<_Receiver>,
- __with_t<get_scheduler_t, _Scheduler>>
- {
- return __make_env(stdexec::get_env(this->base()),
- __with(get_scheduler, __op_state_->__scheduler_));
- }
+ using __id = __receiver_ref;
+ stdexec::__t<__operation<_SchedulerId, _SenderId, _ReceiverId>>*
+ __op_state_;
+ _Receiver&& base() && noexcept
+ {
+ return (_Receiver &&) __op_state_->__rcvr_;
+ }
+ const _Receiver& base() const& noexcept
+ {
+ return __op_state_->__rcvr_;
+ }
+ auto get_env() const
+ -> __make_env_t<env_of_t<_Receiver>,
+ __with<get_scheduler_t, _Scheduler>>
+ {
+ return __make_env(
+ stdexec::get_env(this->base()),
+ __with_(get_scheduler, __op_state_->__scheduler_));
+ }
+ };
};
template <class _SchedulerId, class _SenderId, class _ReceiverId>
-struct __receiver :
- receiver_adaptor<__receiver<_SchedulerId, _SenderId, _ReceiverId>>
+struct __receiver
{
using _Scheduler = stdexec::__t<_SchedulerId>;
using _Sender = stdexec::__t<_SenderId>;
using _Receiver = stdexec::__t<_ReceiverId>;
- using __receiver_ref_t =
- __receiver_ref<_SchedulerId, _SenderId, _ReceiverId>;
- __operation<_SchedulerId, _SenderId, _ReceiverId>* __op_state_;
- _Receiver&& base() && noexcept
- {
- return (_Receiver &&) __op_state_->__rcvr_;
- }
- const _Receiver& base() const& noexcept
- {
- return __op_state_->__rcvr_;
- }
- void set_value() && noexcept
+ struct __t : receiver_adaptor<__t>
{
- // cache this locally since *this is going bye-bye.
- auto* __op_state = __op_state_;
- try
+ using __id = __receiver;
+ using __receiver_ref_t =
+ stdexec::__t<__receiver_ref<_SchedulerId, _SenderId, _ReceiverId>>;
+ stdexec::__t<__operation<_SchedulerId, _SenderId, _ReceiverId>>*
+ __op_state_;
+ _Receiver&& base() && noexcept
{
- // This line will invalidate *this:
- start(__op_state->__data_.template emplace<1>(__conv{[__op_state] {
- return connect((_Sender &&) __op_state->__sndr_,
- __receiver_ref_t{{}, __op_state});
- }}));
+ return (_Receiver &&) __op_state_->__rcvr_;
}
- catch (...)
+ const _Receiver& base() const& noexcept
{
- set_error((_Receiver &&) __op_state->__rcvr_,
- std::current_exception());
+ return __op_state_->__rcvr_;
}
- }
+
+ void set_value() && noexcept
+ {
+ // cache this locally since *this is going bye-bye.
+ auto* __op_state = __op_state_;
+ try
+ {
+ // This line will invalidate *this:
+ start(__op_state->__data_.template emplace<1>(
+ __conv{[__op_state] {
+ return connect((_Sender &&) __op_state->__sndr_,
+ __receiver_ref_t{{}, __op_state});
+ }}));
+ }
+ catch (...)
+ {
+ set_error((_Receiver &&) __op_state->__rcvr_,
+ std::current_exception());
+ }
+ }
+ };
};
template <class _SchedulerId, class _SenderId, class _ReceiverId>
struct __operation
{
- using _Scheduler = __t<_SchedulerId>;
- using _Sender = __t<_SenderId>;
- using _Receiver = __t<_ReceiverId>;
- using __receiver_t = __receiver<_SchedulerId, _SenderId, _ReceiverId>;
- using __receiver_ref_t =
- __receiver_ref<_SchedulerId, _SenderId, _ReceiverId>;
+ using _Scheduler = stdexec::__t<_SchedulerId>;
+ using _Sender = stdexec::__t<_SenderId>;
+ using _Receiver = stdexec::__t<_ReceiverId>;
- friend void tag_invoke(start_t, __operation& __self) noexcept
+ struct __t
{
- start(std::get<0>(__self.__data_));
- }
+ using __id = __operation;
+ using __receiver_t =
+ stdexec::__t<__receiver<_SchedulerId, _SenderId, _ReceiverId>>;
+ using __receiver_ref_t =
+ stdexec::__t<__receiver_ref<_SchedulerId, _SenderId, _ReceiverId>>;
- template <class _Sender2, class _Receiver2>
- __operation(_Scheduler __sched, _Sender2&& __sndr, _Receiver2&& __rcvr) :
- __scheduler_((_Scheduler &&) __sched), __sndr_((_Sender2 &&) __sndr),
- __rcvr_((_Receiver2 &&) __rcvr),
- __data_{std::in_place_index<0>, __conv{[&, this] {
+ friend void tag_invoke(start_t, __t& __self) noexcept
+ {
+ start(std::get<0>(__self.__data_));
+ }
+
+ template <class _Sender2, class _Receiver2>
+ __t(_Scheduler __sched, _Sender2&& __sndr, _Receiver2&& __rcvr) :
+ __scheduler_((_Scheduler &&) __sched),
+ __sndr_((_Sender2 &&) __sndr), __rcvr_((_Receiver2 &&) __rcvr),
+ __data_{
+ std::in_place_index<0>, __conv{[&, this] {
return connect(schedule(__sched), __receiver_t{{}, this});
}}}
- {}
- STDEXEC_IMMOVABLE(__operation);
+ {}
+ STDEXEC_IMMOVABLE(__t);
- _Scheduler __scheduler_;
- _Sender __sndr_;
- _Receiver __rcvr_;
- std::variant<connect_result_t<schedule_result_t<_Scheduler>, __receiver_t>,
- connect_result_t<_Sender, __receiver_ref_t>>
- __data_;
+ _Scheduler __scheduler_;
+ _Sender __sndr_;
+ _Receiver __rcvr_;
+ std::variant<
+ connect_result_t<schedule_result_t<_Scheduler>, __receiver_t>,
+ connect_result_t<_Sender, __receiver_ref_t>>
+ __data_;
+ };
};
template <class _SchedulerId, class _SenderId>
struct __sender
{
- using _Scheduler = __t<_SchedulerId>;
- using _Sender = __t<_SenderId>;
- template <class _ReceiverId>
- using __receiver_ref_t =
- __receiver_ref<_SchedulerId, _SenderId, _ReceiverId>;
- template <class _ReceiverId>
- using __receiver_t = __receiver<_SchedulerId, _SenderId, _ReceiverId>;
- template <class _ReceiverId>
- using __operation_t = __operation<_SchedulerId, _SenderId, _ReceiverId>;
+ using _Scheduler = stdexec::__t<_SchedulerId>;
+ using _Sender = stdexec::__t<_SenderId>;
- _Scheduler __scheduler_;
- _Sender __sndr_;
-
- template <__decays_to<__sender> _Self, receiver _Receiver>
- requires constructible_from<_Sender, __member_t<_Self, _Sender>> &&
- sender_to<schedule_result_t<_Scheduler>,
- __receiver_t<__x<decay_t<_Receiver>>>> &&
- sender_to<_Sender, __receiver_ref_t<__x<decay_t<_Receiver>>>>
- friend auto tag_invoke(connect_t, _Self&& __self,
- _Receiver&& __rcvr)
- -> __operation_t<__x<decay_t<_Receiver>>>
+ struct __t
{
- return {((_Self &&) __self).__scheduler_, ((_Self &&) __self).__sndr_,
- (_Receiver &&) __rcvr};
- }
+ using __id = __sender;
+ template <class _ReceiverId>
+ using __receiver_ref_t =
+ stdexec::__t<__receiver_ref<_SchedulerId, _SenderId, _ReceiverId>>;
+ template <class _ReceiverId>
+ using __receiver_t =
+ stdexec::__t<__receiver<_SchedulerId, _SenderId, _ReceiverId>>;
+ template <class _ReceiverId>
+ using __operation_t =
+ stdexec::__t<__operation<_SchedulerId, _SenderId, _ReceiverId>>;
- template <tag_category<forwarding_sender_query> _Tag, class... _As>
- requires __callable<_Tag, const _Sender&, _As...>
- friend auto
- tag_invoke(_Tag __tag, const __sender& __self, _As&&... __as) noexcept(
- __nothrow_callable<_Tag, const _Sender&, _As...>)
+ _Scheduler __scheduler_;
+ _Sender __sndr_;
+
+ template <__decays_to<__t> _Self, receiver _Receiver>
+ requires constructible_from<_Sender,
+ __copy_cvref_t<_Self, _Sender>> &&
+ sender_to<schedule_result_t<_Scheduler>,
+ __receiver_t<stdexec::__id<_Receiver>>> &&
+ sender_to<_Sender,
+ __receiver_ref_t<stdexec::__id<_Receiver>>>
+ friend auto tag_invoke(connect_t, _Self&& __self,
+ _Receiver __rcvr)
+ -> __operation_t<stdexec::__id<_Receiver>>
+ {
+ return {((_Self &&) __self).__scheduler_,
+ ((_Self &&) __self).__sndr_, (_Receiver &&) __rcvr};
+ }
+
+ template <tag_category<forwarding_sender_query> _Tag, class... _As>
+ requires __callable<_Tag, const _Sender&, _As...>
+ friend auto tag_invoke(
+ _Tag __tag, const __t& __self,
+ _As&&... __as) noexcept(__nothrow_callable<_Tag, const _Sender&,
+ _As...>)
-> __call_result_if_t<tag_category<_Tag, forwarding_sender_query>,
_Tag, const _Sender&, _As...>
- {
- return ((_Tag &&) __tag)(__self.__sndr_, (_As &&) __as...);
- }
+ {
+ return ((_Tag &&) __tag)(__self.__sndr_, (_As &&) __as...);
+ }
- template <class...>
- using __value_t = completion_signatures<>;
+ template <class...>
+ using __value_t = completion_signatures<>;
- template <__decays_to<__sender> _Self, class _Env>
- friend auto tag_invoke(get_completion_signatures_t, _Self&&, _Env)
- -> make_completion_signatures<
- schedule_result_t<_Scheduler>, _Env,
- make_completion_signatures<
- __member_t<_Self, _Sender>,
- __make_env_t<_Env, __with_t<get_scheduler_t, _Scheduler>>,
- completion_signatures<set_error_t(std::exception_ptr)>>,
- __value_t>;
+ template <__decays_to<__t> _Self, class _Env>
+ friend auto tag_invoke(get_completion_signatures_t, _Self&&, _Env)
+ -> make_completion_signatures<
+ schedule_result_t<_Scheduler>, _Env,
+ make_completion_signatures<
+ __copy_cvref_t<_Self, _Sender>,
+ __make_env_t<_Env, __with<get_scheduler_t, _Scheduler>>,
+ completion_signatures<set_error_t(std::exception_ptr)>>,
+ __value_t>;
+ };
};
-} // namespace __impl
struct on_t
{
@@ -5237,7 +5334,8 @@
template <scheduler _Scheduler, sender _Sender>
auto operator()(_Scheduler&& __sched, _Sender&& __sndr) const
- -> __impl::__sender<__x<decay_t<_Scheduler>>, __x<decay_t<_Sender>>>
+ -> __t<__sender<stdexec::__id<decay_t<_Scheduler>>,
+ stdexec::__id<decay_t<_Sender>>>>
{
// connect-based customization will remove the need for this check
using __has_customizations =
@@ -5297,98 +5395,113 @@
using __into_variant_result_t = value_types_of_t<_Sender, _Env>;
template <class _SenderId, class _ReceiverId>
-class __receiver :
- receiver_adaptor<__receiver<_SenderId, _ReceiverId>, __t<_ReceiverId>>
+struct __receiver
{
-#if STDEXEC_NON_LEXICAL_FRIENDSHIP
- public:
-#endif
- using _Sender = stdexec::__t<_SenderId>;
using _Receiver = stdexec::__t<_ReceiverId>;
- friend receiver_adaptor<__receiver, _Receiver>;
- // Customize set_value by building a variant and passing the result
- // to the base class
- template <class... _As>
- void set_value(_As&&... __as) && noexcept
- try
+ class __t : receiver_adaptor<__t, _Receiver>
{
- using __variant_t =
- __into_variant_result_t<_Sender, env_of_t<_Receiver>>;
- static_assert(constructible_from<__variant_t, std::tuple<_As&&...>>);
- stdexec::set_value(((__receiver &&) * this).base(),
- __variant_t{std::tuple<_As&&...>{(_As &&) __as...}});
- }
- catch (...)
- {
- stdexec::set_error(((__receiver &&) * this).base(),
- std::current_exception());
- }
+#if STDEXEC_NON_LEXICAL_FRIENDSHIP
+ public:
+#endif
+ using _Sender = stdexec::__t<_SenderId>;
+ using _Receiver = stdexec::__t<_ReceiverId>;
+ friend receiver_adaptor<__t, _Receiver>;
- public:
- using receiver_adaptor<__receiver, _Receiver>::receiver_adaptor;
+ // Customize set_value by building a variant and passing the result
+ // to the base class
+ template <class... _As>
+ void set_value(_As&&... __as) && noexcept
+ try
+ {
+ using __variant_t =
+ __into_variant_result_t<_Sender, env_of_t<_Receiver>>;
+ static_assert(
+ constructible_from<__variant_t, std::tuple<_As&&...>>);
+ stdexec::set_value(
+ ((__t &&) * this).base(),
+ __variant_t{std::tuple<_As&&...>{(_As &&) __as...}});
+ }
+ catch (...)
+ {
+ stdexec::set_error(((__t &&) * this).base(),
+ std::current_exception());
+ }
+
+ public:
+ using __id = __receiver;
+ using receiver_adaptor<__t, _Receiver>::receiver_adaptor;
+ };
};
template <class _SenderId>
-class __sender
+struct __sender
{
- using _Sender = __t<_SenderId>;
- friend sender_adaptor<__sender, _Sender>;
+ using _Sender = stdexec::__t<_SenderId>;
+
template <class _Receiver>
- using __receiver_t = __receiver<_SenderId, __x<remove_cvref_t<_Receiver>>>;
+ using __receiver_t =
+ stdexec::__t<__receiver<_SenderId, stdexec::__id<_Receiver>>>;
- template <class...>
- using __value_t = completion_signatures<>;
-
- template <class _Env>
- using __compl_sigs = make_completion_signatures<
- _Sender, _Env,
- completion_signatures<set_value_t(
- __into_variant_result_t<_Sender, _Env>),
- set_error_t(std::exception_ptr)>,
- __value_t>;
-
- _Sender __sndr_;
-
- template <receiver _Receiver>
- requires sender_to<_Sender, __receiver_t<_Receiver>>
- friend auto
- tag_invoke(connect_t, __sender&& __self, _Receiver&& __rcvr) noexcept(
- __nothrow_connectable<_Sender, __receiver_t<_Receiver>>)
- -> connect_result_t<_Sender, __receiver_t<_Receiver>>
+ class __t
{
- return stdexec::connect((_Sender &&) __self.__sndr_,
- __receiver_t<_Receiver>{(_Receiver &&) __rcvr});
- }
+ template <class...>
+ using __value_t = completion_signatures<>;
- template <tag_category<forwarding_sender_query> _Tag, class... _As>
- requires __callable<_Tag, const _Sender&, _As...>
- friend auto
- tag_invoke(_Tag __tag, const __sender& __self, _As&&... __as) noexcept(
- __nothrow_callable<_Tag, const _Sender&, _As...>)
+ template <class _Env>
+ using __compl_sigs = make_completion_signatures<
+ _Sender, _Env,
+ completion_signatures<set_value_t(
+ __into_variant_result_t<_Sender, _Env>),
+ set_error_t(std::exception_ptr)>,
+ __value_t>;
+
+ _Sender __sndr_;
+
+ template <receiver _Receiver>
+ requires sender_to<_Sender, __receiver_t<_Receiver>>
+ friend auto
+ tag_invoke(connect_t, __t&& __self, _Receiver __rcvr) noexcept(
+ __nothrow_connectable<_Sender, __receiver_t<_Receiver>>)
+ -> connect_result_t<_Sender, __receiver_t<_Receiver>>
+ {
+ return stdexec::connect(
+ (_Sender &&) __self.__sndr_,
+ __receiver_t<_Receiver>{(_Receiver &&) __rcvr});
+ }
+
+ template <tag_category<forwarding_sender_query> _Tag, class... _As>
+ requires __callable<_Tag, const _Sender&, _As...>
+ friend auto tag_invoke(
+ _Tag __tag, const __t& __self,
+ _As&&... __as) noexcept(__nothrow_callable<_Tag, const _Sender&,
+ _As...>)
-> __call_result_if_t<tag_category<_Tag, forwarding_sender_query>,
_Tag, const _Sender&, _As...>
- {
- return ((_Tag &&) __tag)(__self.__sndr_, (_As &&) __as...);
- }
+ {
+ return ((_Tag &&) __tag)(__self.__sndr_, (_As &&) __as...);
+ }
- template <class _Env>
- friend auto tag_invoke(get_completion_signatures_t, __sender&&, _Env)
- -> __compl_sigs<_Env>;
+ template <class _Env>
+ friend auto tag_invoke(get_completion_signatures_t, __t&&, _Env)
+ -> __compl_sigs<_Env>;
- public:
- template <__decays_to<_Sender> _CvrefSender>
- explicit __sender(_CvrefSender&& __sndr) : __sndr_((_CvrefSender &&) __sndr)
- {}
+ public:
+ using __id = __sender;
+ template <__decays_to<_Sender> _CvrefSender>
+ explicit __t(_CvrefSender&& __sndr) : __sndr_((_CvrefSender &&) __sndr)
+ {}
+ };
};
struct into_variant_t
{
template <sender _Sender>
auto operator()(_Sender&& __sndr) const
- -> __sender<__x<remove_cvref_t<_Sender>>>
+ -> __t<__sender<stdexec::__id<remove_cvref_t<_Sender>>>>
{
- return __sender<__x<remove_cvref_t<_Sender>>>{(_Sender &&) __sndr};
+ return __t<__sender<stdexec::__id<remove_cvref_t<_Sender>>>>{
+ (_Sender &&) __sndr};
}
auto operator()() const noexcept
{
@@ -5404,8 +5517,6 @@
// [execution.senders.adaptors.when_all_with_variant]
namespace __when_all
{
-namespace __impl
-{
enum __state_t
{
__started,
@@ -5422,79 +5533,170 @@
}
};
-template <class _Env>
-using __env_t =
- __make_env_t<_Env, __with_t<get_stop_token_t, in_place_stop_token>>;
-
-template <class...>
-using __swallow_values = completion_signatures<>;
-
-template <class _Env, class... _Senders>
-struct __traits
+template <class _EnvId>
+struct __env
{
- using __t = dependent_completion_signatures<_Env>;
-};
-
-template <class _Env, class... _Senders>
- requires((__v<__count_of<set_value_t, _Senders, _Env>> <= 1) && ...)
-struct __traits<_Env, _Senders...>
-{
- using __non_values = __concat_completion_signatures_t<
- completion_signatures<set_error_t(std::exception_ptr), set_stopped_t()>,
- make_completion_signatures<_Senders, _Env, completion_signatures<>,
- __swallow_values>...>;
- using __values = __minvoke<__concat<__qf<set_value_t>>,
- __value_types_of_t<_Senders, _Env, __q<__types>,
- __single_or<__types<>>>...>;
- using __t = __if_c<(__sends<set_value_t, _Senders, _Env> && ...),
- __minvoke2<__push_back<__q<completion_signatures>>,
- __non_values, __values>,
- __non_values>;
-};
-
-template <class... _SenderIds>
-struct __sender
-{
- template <class... _Sndrs>
- explicit __sender(_Sndrs&&... __sndrs) : __sndrs_((_Sndrs &&) __sndrs...)
- {}
-
- private:
- template <class _CvrefEnv>
- using __completion_sigs =
- __t<__traits<__env_t<remove_cvref_t<_CvrefEnv>>,
- __member_t<_CvrefEnv, __t<_SenderIds>>...>>;
-
- template <class _Traits>
- using __sends_values =
- __bool<__v<typename _Traits::template __gather_sigs<
- set_value_t, __mconst<int>, __mcount>> != 0>;
-
- template <class _CvrefReceiverId>
- struct __operation;
-
- template <class _CvrefReceiverId, std::size_t _Index>
- struct __receiver : receiver_adaptor<__receiver<_CvrefReceiverId, _Index>>
+ using _Env = stdexec::__t<_EnvId>;
+ struct __t
{
- using _WhenAll = __member_t<_CvrefReceiverId, __sender>;
- using _Receiver = stdexec::__t<decay_t<_CvrefReceiverId>>;
- using _Traits = __completion_sigs<
- __member_t<_CvrefReceiverId, env_of_t<_Receiver>>>;
+ using __id = __env;
+ _Env __base_env_;
+ in_place_stop_token __stok_;
- _Receiver&& base() && noexcept
+ friend in_place_stop_token tag_invoke(get_stop_token_t,
+ const __t& __self) noexcept
{
- return (_Receiver &&) __op_state_->__recvr_;
+ return __self.__stok_;
}
- const _Receiver& base() const& noexcept
+
+ // Forward the receiver queries:
+ template <__none_of<get_completion_signatures_t, get_stop_token_t> _Tag,
+ same_as<__t> _Self, class... _As>
+ requires __callable<_Tag, const __make_dependent_on<_Env, _Self>&,
+ _As...>
+ friend auto tag_invoke(_Tag __tag, const _Self& __self,
+ _As&&... __as) noexcept
+ -> __call_result_if_t<same_as<_Self, __t>, _Tag,
+ const __make_dependent_on<_Env, _Self>&,
+ _As...>
{
- return __op_state_->__recvr_;
+ return ((_Tag &&) __tag)(__self.__base_env_, (_As &&) __as...);
}
+ };
+};
+
+template <class _Env>
+using __env_t = __t<__if_c<same_as<_Env, no_env>, no_env, __env<__id<_Env>>>>;
+
+template <class _T>
+using __decay_rvalue_ref = decay_t<_T>&&;
+
+template <class _Sender, class _Env>
+concept __max1_sender = sender<_Sender, _Env> &&
+ __valid<__value_types_of_t, _Sender, _Env,
+ __mconst<int>, __msingle_or<void>>;
+
+template <class _Env, class _Sender>
+using __single_values_of_t =
+ __value_types_of_t<_Sender, _Env,
+ __transform<__q<__decay_rvalue_ref>, __q<__types>>,
+ __q<__msingle>>;
+
+template <class _Env, class... _Senders>
+using __set_values_sig_t =
+ completion_signatures<__minvoke<__mconcat<__qf<set_value_t>>,
+ __single_values_of_t<_Env, _Senders>...>>;
+
+template <class _Env, class... _Senders>
+using __completions_t = __concat_completion_signatures_t<
+ completion_signatures<set_error_t(std::exception_ptr&&), // TODO add this
+ // only if the
+ // copies can fail
+ set_stopped_t()>,
+ __minvoke<__with_default<__mbind_front_q<__set_values_sig_t, _Env>,
+ completion_signatures<>>,
+ _Senders...>,
+ __make_completion_signatures<
+ _Senders, _Env, completion_signatures<>,
+ __mconst<completion_signatures<>>,
+ __mcompose<__q<completion_signatures>, __qf<set_error_t>,
+ __q<__decay_rvalue_ref>>>...>;
+
+struct __tie_fn
+{
+ template <class... _Ty>
+ std::tuple<_Ty&...> operator()(_Ty&... __vals) noexcept
+ {
+ return std::tuple<_Ty&...>{__vals...};
+ }
+};
+
+template <class _Tag, class _Receiver>
+struct __complete_fn
+{
+ _Receiver& __rcvr_;
+ __complete_fn(_Tag, _Receiver& __rcvr) noexcept : __rcvr_(__rcvr) {}
+ template <class... _Ts>
+ void operator()(_Ts&... __ts) const noexcept
+ {
+ _Tag{}((_Receiver &&) __rcvr_, (_Ts &&) __ts...);
+ }
+};
+
+template <class _Receiver, class _ValuesTuple>
+void __set_values(_Receiver& __rcvr, _ValuesTuple& __values) noexcept
+{
+ std::apply(
+ [&](auto&... __opt_vals) noexcept -> void {
+ std::apply(__complete_fn{set_value, __rcvr},
+ std::tuple_cat(std::apply(__tie_fn{}, *__opt_vals)...));
+ },
+ __values);
+}
+
+template <class _ReceiverId, class _ValuesTuple, class _ErrorsVariant>
+struct __operation_base : __immovable
+{
+ using _Receiver = stdexec::__t<_ReceiverId>;
+
+ void __arrive() noexcept
+ {
+ if (0 == --__count_)
+ {
+ __complete();
+ }
+ }
+
+ void __complete() noexcept
+ {
+ // Stop callback is no longer needed. Destroy it.
+ __on_stop_.reset();
+ // All child operations have completed and arrived at the barrier.
+ switch (__state_.load(std::memory_order_relaxed))
+ {
+ case __started:
+ if constexpr (!same_as<_ValuesTuple, __ignore>)
+ {
+ // All child operations completed successfully:
+ __when_all::__set_values(__recvr_, __values_);
+ }
+ break;
+ case __error:
+ std::visit(__complete_fn{set_error, __recvr_}, __errors_);
+ break;
+ case __stopped:
+ stdexec::set_stopped((_Receiver &&) __recvr_);
+ break;
+ default:;
+ }
+ }
+
+ _Receiver __recvr_;
+ std::atomic<std::size_t> __count_;
+ in_place_stop_source __stop_source_{};
+ // Could be non-atomic here and atomic_ref everywhere except __completion_fn
+ std::atomic<__state_t> __state_{__started};
+ _ErrorsVariant __errors_{};
+ [[no_unique_address]] _ValuesTuple __values_{};
+ std::optional<typename stop_token_of_t<
+ env_of_t<_Receiver>&>::template callback_type<__on_stop_requested>>
+ __on_stop_{};
+};
+
+template <std::size_t _Index, class _ReceiverId, class _ValuesTuple,
+ class _ErrorsVariant>
+struct __receiver
+{
+ using _Receiver = stdexec::__t<_ReceiverId>;
+
+ struct __t
+ {
+ using __id = __receiver;
template <class _Error>
- void __set_error(_Error&& __err, __state_t __expected) noexcept
+ void __set_error(_Error&& __err) noexcept
{
- // TODO: _What memory orderings are actually needed here?
- if (__op_state_->__state_.compare_exchange_strong(__expected,
- __error))
+ // TODO: What memory orderings are actually needed here?
+ if (__error != __op_state_->__state_.exchange(__error))
{
__op_state_->__stop_source_.request_stop();
// We won the race, free to write the error into the operation
@@ -5510,160 +5712,150 @@
std::current_exception());
}
}
- __op_state_->__arrive();
}
template <class... _Values>
- void set_value(_Values&&... __vals) && noexcept
+ friend void tag_invoke(set_value_t, __t&& __self,
+ _Values&&... __vals) noexcept
{
- if constexpr (__sends_values<_Traits>::value)
+ if constexpr (!same_as<_ValuesTuple, __ignore>)
{
+ using _TupleType =
+ typename std::tuple_element_t<_Index,
+ _ValuesTuple>::value_type;
+ static_assert(
+ same_as<_TupleType, std::tuple<decay_t<_Values>...>>,
+ "One of the senders in this when_all() is fibbing about what types it sends");
// We only need to bother recording the completion values
// if we're not already in the "error" or "stopped" state.
- if (__op_state_->__state_ == __started)
+ if (__self.__op_state_->__state_ == __started)
{
try
{
- std::get<_Index>(__op_state_->__values_)
+ std::get<_Index>(__self.__op_state_->__values_)
.emplace((_Values &&) __vals...);
}
catch (...)
{
- __set_error(std::current_exception(), __started);
+ __self.__set_error(std::current_exception());
}
}
}
- __op_state_->__arrive();
+ __self.__op_state_->__arrive();
}
template <class _Error>
- requires tag_invocable<set_error_t, _Receiver, _Error>
- void set_error(_Error&& __err) && noexcept
+ friend void tag_invoke(set_error_t, __t&& __self,
+ _Error&& __err) noexcept
{
- __set_error((_Error &&) __err, __started);
+ __self.__set_error((_Error &&) __err);
+ __self.__op_state_->__arrive();
}
- void set_stopped() && noexcept
+ friend void tag_invoke(set_stopped_t, __t&& __self) noexcept
{
__state_t __expected = __started;
// Transition to the "stopped" state if and only if we're in the
// "started" state. (If this fails, it's because we're in an
// error state, which trumps cancellation.)
- if (__op_state_->__state_.compare_exchange_strong(__expected,
- __stopped))
+ if (__self.__op_state_->__state_.compare_exchange_strong(__expected,
+ __stopped))
{
- __op_state_->__stop_source_.request_stop();
+ __self.__op_state_->__stop_source_.request_stop();
}
- __op_state_->__arrive();
+ __self.__op_state_->__arrive();
}
- auto get_env() const
- -> __make_env_t<env_of_t<_Receiver>,
- __with_t<get_stop_token_t, in_place_stop_token>>
+ friend __env_t<env_of_t<_Receiver>> tag_invoke(get_env_t,
+ const __t& __self)
{
- return __make_env(stdexec::get_env(base()),
- __with(get_stop_token,
- __op_state_->__stop_source_.get_token()));
+ return {stdexec::get_env(__self.__op_state_->__recvr_),
+ __self.__op_state_->__stop_source_.get_token()};
}
- __operation<_CvrefReceiverId>* __op_state_;
+ __operation_base<_ReceiverId, _ValuesTuple, _ErrorsVariant>*
+ __op_state_;
};
+};
- template <class _CvrefReceiverId>
- struct __operation
+template <class _Env, class _Sender>
+using __values_opt_tuple_t =
+ __value_types_of_t<_Sender, __env_t<__id<_Env>>,
+ __mcompose<__q<std::optional>, __q<__decayed_tuple>>,
+ __q<__msingle>>;
+
+template <class _Env, __max1_sender<__env_t<_Env>>... _Senders>
+struct __traits_
+{
+ using __completions = __completions_t<__env_t<_Env>, _Senders...>;
+
+ // tuple<optional<tuple<Vs1...>>, optional<tuple<Vs2...>>, ...>
+ using __values_tuple = __minvoke<
+ __with_default<__transform<__mbind_front_q<__values_opt_tuple_t, _Env>,
+ __q<std::tuple>>,
+ __ignore>,
+ _Senders...>;
+
+ using __errors_variant =
+ __minvoke<__mconcat<__q<__variant>>, __types<std::exception_ptr>,
+ error_types_of_t<_Senders, __env_t<__id<_Env>>, __types>...>;
+};
+
+template <receiver _Receiver,
+ __max1_sender<__env_t<env_of_t<_Receiver>>>... _Senders>
+struct __traits : __traits_<env_of_t<_Receiver>, _Senders...>
+{
+ using _Traits = __traits_<env_of_t<_Receiver>, _Senders...>;
+ using typename _Traits::__completions;
+ using typename _Traits::__errors_variant;
+ using typename _Traits::__values_tuple;
+
+ template <std::size_t _Index>
+ using __receiver =
+ __t<__when_all::__receiver<_Index, __id<_Receiver>, __values_tuple,
+ __errors_variant>>;
+
+ using __operation_base =
+ __when_all::__operation_base<__id<_Receiver>, __values_tuple,
+ __errors_variant>;
+
+ template <class _Sender, class _Index>
+ using __op_state = connect_result_t<_Sender, __receiver<__v<_Index>>>;
+
+ using __op_states_tuple =
+ __minvoke<__mzip_with2<__q<__op_state>, __q<std::tuple>>,
+ __types<_Senders...>, __mindex_sequence_for<_Senders...>>;
+};
+
+template <class _Cvref, class _ReceiverId, class... _SenderIds>
+struct __operation
+{
+ using _Receiver = stdexec::__t<_ReceiverId>;
+ using _Traits =
+ __traits<_Receiver, __minvoke<_Cvref, stdexec::__t<_SenderIds>>...>;
+ using _Indices = std::index_sequence_for<_SenderIds...>;
+
+ using __operation_base_t = typename _Traits::__operation_base;
+ using __op_states_tuple_t = typename _Traits::__op_states_tuple;
+
+ template <std::size_t _Index>
+ using __receiver_t = typename _Traits::template __receiver<_Index>;
+
+ struct __t : __operation_base_t
{
- using _WhenAll = __member_t<_CvrefReceiverId, __sender>;
- using _Receiver = __t<decay_t<_CvrefReceiverId>>;
- using _Env = env_of_t<_Receiver>;
- using _CvrefEnv = __member_t<_CvrefReceiverId, _Env>;
- using _Traits = __completion_sigs<_CvrefEnv>;
+ using __id = __operation;
- template <class _Sender, class _Index>
- using __child_op_state_t =
- connect_result_t<__member_t<_WhenAll, _Sender>,
- __receiver<_CvrefReceiverId, __v<_Index>>>;
-
- using _Indices = std::index_sequence_for<_SenderIds...>;
-
- template <size_t... _Is>
- static auto __connect_children_(std::index_sequence<_Is...>)
- -> std::tuple<__child_op_state_t<__t<_SenderIds>, __index<_Is>>...>;
-
- using __child_op_states_tuple_t =
- decltype(__operation::__connect_children_(_Indices{}));
-
- void __arrive() noexcept
- {
- if (0 == --__count_)
- {
- __complete();
- }
- }
-
- void __complete() noexcept
- {
- // Stop callback is no longer needed. Destroy it.
- __on_stop_.reset();
- // All child operations have completed and arrived at the barrier.
- switch (__state_.load(std::memory_order_relaxed))
- {
- case __started:
- if constexpr (__sends_values<_Traits>::value)
- {
- // All child operations completed successfully:
- std::apply(
- [this](auto&... __opt_vals) -> void {
- std::apply(
- [this](auto&... __all_vals) -> void {
- try
- {
- stdexec::set_value(
- (_Receiver &&) __recvr_,
- std::move(__all_vals)...);
- }
- catch (...)
- {
- stdexec::set_error(
- (_Receiver &&) __recvr_,
- std::current_exception());
- }
- },
- std::tuple_cat(std::apply(
- [](auto&... __vals) {
- return std::tie(__vals...);
- },
- *__opt_vals)...));
- },
- __values_);
- }
- break;
- case __error:
- std::visit(
- [this](auto& __err) noexcept {
- stdexec::set_error((_Receiver &&) __recvr_,
- std::move(__err));
- },
- __errors_);
- break;
- case __stopped:
- stdexec::set_stopped((_Receiver &&) __recvr_);
- break;
- default:;
- }
- }
-
- template <size_t... _Is>
- __operation(_WhenAll&& __when_all, _Receiver __rcvr,
- std::index_sequence<_Is...>) :
- __recvr_((_Receiver &&) __rcvr),
- __child_states_{__conv{[&__when_all, this]() {
+ template <class _SendersTuple, std::size_t... _Is>
+ __t(_SendersTuple&& __sndrs, _Receiver __rcvr,
+ std::index_sequence<_Is...>) :
+ __operation_base_t{{}, (_Receiver &&) __rcvr, {sizeof...(_Is)}},
+ __op_states_{__conv{[&__sndrs, this]() {
return stdexec::connect(
- std::get<_Is>(((_WhenAll &&) __when_all).__sndrs_),
- __receiver<_CvrefReceiverId, _Is>{{}, this});
+ std::get<_Is>((_SendersTuple &&) __sndrs),
+ __receiver_t<_Is>{this});
}}...}
{}
- __operation(_WhenAll&& __when_all, _Receiver __rcvr) :
- __operation((_WhenAll &&) __when_all, (_Receiver &&) __rcvr,
- _Indices{})
+ template <class _SendersTuple>
+ __t(_SendersTuple&& __sndrs, _Receiver __rcvr) :
+ __t((_SendersTuple &&) __sndrs, (_Receiver &&) __rcvr, _Indices{})
{}
- STDEXEC_IMMOVABLE(__operation);
- friend void tag_invoke(start_t, __operation& __self) noexcept
+ friend void tag_invoke(start_t, __t& __self) noexcept
{
// register stop callback:
__self.__on_stop_.emplace(
@@ -5677,11 +5869,11 @@
}
else
{
- apply(
- [](auto&&... __child_ops) noexcept -> void {
+ std::apply(
+ [](auto&... __child_ops) noexcept -> void {
(stdexec::start(__child_ops), ...);
},
- __self.__child_states_);
+ __self.__op_states_);
if constexpr (sizeof...(_SenderIds) == 0)
{
__self.__complete();
@@ -5689,50 +5881,75 @@
}
}
- // tuple<optional<tuple<Vs1...>>, optional<tuple<Vs2...>>, ...>
- using __child_values_tuple_t =
- __if<__sends_values<_Traits>,
- __minvoke<__q<std::tuple>,
- __value_types_of_t<__t<_SenderIds>, __env_t<_Env>,
- __mcompose<__q1<std::optional>,
- __q<__decayed_tuple>>,
- __single_or<void>>...>,
- __>;
-
- in_place_stop_source __stop_source_{};
- _Receiver __recvr_;
- std::atomic<std::size_t> __count_{sizeof...(_SenderIds)};
- // Could be non-atomic here and atomic_ref everywhere except
- // __completion_fn
- std::atomic<__state_t> __state_{__started};
- error_types_of_t<__sender, __env_t<_Env>, __variant> __errors_{};
- [[no_unique_address]] __child_values_tuple_t __values_{};
- std::optional<typename stop_token_of_t<
- env_of_t<_Receiver>&>::template callback_type<__on_stop_requested>>
- __on_stop_{};
- __child_op_states_tuple_t __child_states_;
+ __op_states_tuple_t __op_states_;
};
+};
- template <__decays_to<__sender> _Self, receiver _Receiver>
- friend auto tag_invoke(connect_t, _Self&& __self, _Receiver&& __rcvr)
- -> __operation<__member_t<_Self, __x<decay_t<_Receiver>>>>
+template <class _From, class _ToId>
+using __cvref_id = __copy_cvref_t<_From, __t<_ToId>>;
+
+template <class _Indices, class... _SenderIds>
+struct __sender;
+
+template <std::size_t... _Indices, class... _SenderIds>
+struct __sender<std::index_sequence<_Indices...>, _SenderIds...>
+{
+ template <class _Self, class _Env>
+ using __completions_t =
+ typename __traits_<_Env,
+ __cvref_id<_Self, _SenderIds>...>::__completions;
+
+ template <class _Self, class _Receiver, std::size_t _Index>
+ using __receiver_t =
+ typename __traits<_Receiver, __cvref_id<_Self, _SenderIds>...>::
+ template __receiver<_Index>;
+
+ template <class _Self, class _Receiver>
+ using __operation_t =
+ stdexec::__t<__operation<__copy_cvref_fn<_Self>,
+ stdexec::__id<_Receiver>, _SenderIds...>>;
+
+ struct __t
{
- return {(_Self &&) __self, (_Receiver &&) __rcvr};
- }
+ using __id = __sender;
- template <__decays_to<__sender> _Self, class _Env>
- friend auto tag_invoke(get_completion_signatures_t, _Self&&, _Env)
- -> __completion_sigs<__member_t<_Self, _Env>>;
+ template <class... _Sndrs>
+ explicit(sizeof...(_Sndrs) == 1) __t(_Sndrs&&... __sndrs) :
+ __sndrs_((_Sndrs &&) __sndrs...)
+ {}
- std::tuple<__t<_SenderIds>...> __sndrs_;
+ private:
+ template <__decays_to<__t> _Self, receiver _Receiver>
+ requires(sender_to<__cvref_id<_Self, _SenderIds>,
+ __receiver_t<_Self, _Receiver, _Indices>> &&
+ ...)
+ friend auto tag_invoke(connect_t, _Self&& __self, _Receiver __rcvr)
+ -> __operation_t<_Self, _Receiver>
+ {
+ return {((_Self &&) __self).__sndrs_, (_Receiver &&) __rcvr};
+ }
+
+ template <__decays_to<__t> _Self, class _Env>
+ friend auto tag_invoke(get_completion_signatures_t, _Self&&, _Env)
+ -> dependent_completion_signatures<_Env>;
+ template <__decays_to<__t> _Self, class _Env>
+ friend auto tag_invoke(get_completion_signatures_t, _Self&&, _Env)
+ -> __completions_t<_Self, _Env>
+ requires true;
+
+ std::tuple<stdexec::__t<_SenderIds>...> __sndrs_;
+ };
};
template <class _Sender>
using __into_variant_result_t = decltype(into_variant(__declval<_Sender>()));
-} // namespace __impl
struct when_all_t
{
+ template <class... _Senders>
+ using __sender_t = __t<__sender<std::index_sequence_for<_Senders...>,
+ __id<decay_t<_Senders>>...>>;
+
template <sender... _Senders>
requires tag_invocable<when_all_t, _Senders...> &&
sender<tag_invoke_result_t<when_all_t, _Senders...>>
@@ -5744,12 +5961,11 @@
}
template <sender... _Senders>
- requires(!tag_invocable<when_all_t, _Senders...>)
- auto operator()(_Senders&&... __sndrs) const
- -> __impl::__sender<__x<decay_t<_Senders>>...>
+ requires(!tag_invocable<when_all_t, _Senders...>) &&
+ sender<__sender_t<_Senders...>>
+ __sender_t<_Senders...> operator()(_Senders&&... __sndrs) const
{
- return __impl::__sender<__x<decay_t<_Senders>>...>{(_Senders &&)
- __sndrs...};
+ return __sender_t<_Senders...>{(_Senders &&) __sndrs...};
}
};
@@ -5844,24 +6060,31 @@
namespace __read
{
template <class _Tag, class _ReceiverId>
-struct __operation : __immovable
+struct __operation
{
- __t<_ReceiverId> __rcvr_;
- friend void tag_invoke(start_t, __operation& __self) noexcept
- try
+ using _Receiver = stdexec::__t<_ReceiverId>;
+ struct __t : __immovable
{
- auto __env = get_env(__self.__rcvr_);
- set_value(std::move(__self.__rcvr_), _Tag{}(__env));
- }
- catch (...)
- {
- set_error(std::move(__self.__rcvr_), std::current_exception());
- }
+ using __id = __operation;
+ _Receiver __rcvr_;
+ friend void tag_invoke(start_t, __t& __self) noexcept
+ try
+ {
+ auto __env = get_env(__self.__rcvr_);
+ set_value(std::move(__self.__rcvr_), _Tag{}(__env));
+ }
+ catch (...)
+ {
+ set_error(std::move(__self.__rcvr_), std::current_exception());
+ }
+ };
};
template <class _Tag>
struct __sender
{
+ using __t = __sender;
+ using __id = __sender;
template <class _Env>
requires __callable<_Tag, _Env>
using __completions_t =
@@ -5870,9 +6093,9 @@
template <class _Receiver>
requires receiver_of<_Receiver, __completions_t<env_of_t<_Receiver>>>
- friend auto tag_invoke(connect_t, __sender, _Receiver&& __rcvr) noexcept(
- std::is_nothrow_constructible_v<decay_t<_Receiver>, _Receiver>)
- -> __operation<_Tag, __x<decay_t<_Receiver>>>
+ friend auto tag_invoke(connect_t, __sender, _Receiver __rcvr) noexcept(
+ std::is_nothrow_move_constructible_v<_Receiver>)
+ -> stdexec::__t<__operation<_Tag, stdexec::__id<_Receiver>>>
{
return {{}, (_Receiver &&) __rcvr};
}
@@ -5897,7 +6120,7 @@
inline constexpr __read::__read_t read{};
-namespace __general_queries
+namespace __queries
{
inline auto get_scheduler_t::operator()() const noexcept
{
@@ -5915,21 +6138,21 @@
{
return read(get_stop_token);
}
-} // namespace __general_queries
+} // namespace __queries
/////////////////////////////////////////////////////////////////////////////
// [execution.senders.consumers.sync_wait]
// [execution.senders.consumers.sync_wait_with_variant]
namespace __sync_wait
{
-namespace __impl
-{
template <class _Sender>
using __into_variant_result_t =
decltype(stdexec::into_variant(__declval<_Sender>()));
struct __env
{
+ using __t = __env;
+ using __id = __env;
stdexec::run_loop::__scheduler __sched_;
friend auto tag_invoke(stdexec::get_scheduler_t,
@@ -5948,114 +6171,110 @@
};
// What should sync_wait(just_stopped()) return?
-template <class _Sender>
- requires stdexec::sender<_Sender, __env>
-using __sync_wait_result_t =
- stdexec::value_types_of_t<_Sender, __env, stdexec::__decayed_tuple,
- __single>;
+template <class _Sender, class _Continuation>
+using __sync_wait_result_impl =
+ __value_types_of_t<_Sender, __env, __transform<__q<decay_t>, _Continuation>,
+ __q<__msingle>>;
+
+template <stdexec::sender<__env> _Sender>
+using __sync_wait_result_t = __sync_wait_result_impl<_Sender, __q<std::tuple>>;
template <class _Sender>
using __sync_wait_with_variant_result_t =
__sync_wait_result_t<__into_variant_result_t<_Sender>>;
-template <class _SenderId>
-struct __state;
-
-template <class _SenderId>
-struct __receiver
-{
- using _Sender = __t<_SenderId>;
- __state<_SenderId>* __state_;
- stdexec::run_loop* __loop_;
- template <class _Error>
- void __set_error(_Error __err) noexcept
- {
- if constexpr (__decays_to<_Error, std::exception_ptr>)
- __state_->__data_.template emplace<2>((_Error &&) __err);
- else if constexpr (__decays_to<_Error, std::error_code>)
- __state_->__data_.template emplace<2>(
- std::make_exception_ptr(std::system_error(__err)));
- else
- __state_->__data_.template emplace<2>(
- std::make_exception_ptr((_Error &&) __err));
- __loop_->finish();
- }
- template <class _Sender2 = _Sender, class... _As>
- requires constructible_from<__sync_wait_result_t<_Sender2>, _As...>
- friend void tag_invoke(stdexec::set_value_t, __receiver&& __rcvr,
- _As&&... __as) noexcept
- try
- {
- __rcvr.__state_->__data_.template emplace<1>((_As &&) __as...);
- __rcvr.__loop_->finish();
- }
- catch (...)
- {
- __rcvr.__set_error(std::current_exception());
- }
- template <class _Error>
- friend void tag_invoke(stdexec::set_error_t, __receiver&& __rcvr,
- _Error __err) noexcept
- {
- __rcvr.__set_error((_Error &&) __err);
- }
- friend void tag_invoke(stdexec::set_stopped_t __d,
- __receiver&& __rcvr) noexcept
- {
- __rcvr.__state_->__data_.template emplace<3>(__d);
- __rcvr.__loop_->finish();
- }
- friend __env tag_invoke(stdexec::get_env_t,
- const __receiver& __rcvr) noexcept
- {
- return {__rcvr.__loop_->get_scheduler()};
- }
-};
-
-template <class _SenderId>
+template <class... _Values>
struct __state
{
- using _Tuple = __sync_wait_result_t<__t<_SenderId>>;
- std::variant<std::monostate, _Tuple, std::exception_ptr,
- stdexec::set_stopped_t>
+ using _Tuple = std::tuple<_Values...>;
+ std::variant<std::monostate, _Tuple, std::exception_ptr, set_stopped_t>
__data_{};
};
+template <class... _Values>
+struct __receiver
+{
+ struct __t
+ {
+ using __id = __receiver;
+ __state<_Values...>* __state_;
+ stdexec::run_loop* __loop_;
+ template <class _Error>
+ void __set_error(_Error __err) noexcept
+ {
+ if constexpr (__decays_to<_Error, std::exception_ptr>)
+ __state_->__data_.template emplace<2>((_Error &&) __err);
+ else if constexpr (__decays_to<_Error, std::error_code>)
+ __state_->__data_.template emplace<2>(
+ std::make_exception_ptr(std::system_error(__err)));
+ else
+ __state_->__data_.template emplace<2>(
+ std::make_exception_ptr((_Error &&) __err));
+ __loop_->finish();
+ }
+ template <class... _As>
+ requires constructible_from<std::tuple<_Values...>, _As...>
+ friend void tag_invoke(stdexec::set_value_t, __t&& __rcvr,
+ _As&&... __as) noexcept
+ try
+ {
+ __rcvr.__state_->__data_.template emplace<1>((_As &&) __as...);
+ __rcvr.__loop_->finish();
+ }
+ catch (...)
+ {
+ __rcvr.__set_error(std::current_exception());
+ }
+ template <class _Error>
+ friend void tag_invoke(stdexec::set_error_t, __t&& __rcvr,
+ _Error __err) noexcept
+ {
+ __rcvr.__set_error((_Error &&) __err);
+ }
+ friend void tag_invoke(stdexec::set_stopped_t __d,
+ __t&& __rcvr) noexcept
+ {
+ __rcvr.__state_->__data_.template emplace<3>(__d);
+ __rcvr.__loop_->finish();
+ }
+ friend __env tag_invoke(stdexec::get_env_t, const __t& __rcvr) noexcept
+ {
+ return {__rcvr.__loop_->get_scheduler()};
+ }
+ };
+};
+
template <class _Sender>
using __into_variant_result_t =
decltype(stdexec::into_variant(__declval<_Sender>()));
-} // namespace __impl
////////////////////////////////////////////////////////////////////////////
// [execution.senders.consumers.sync_wait]
struct sync_wait_t
{
+ template <class _Sender>
+ using __receiver_t = __t<__sync_wait_result_impl<_Sender, __q<__receiver>>>;
+
// TODO: constrain on return type
- template <stdexec::__single_value_variant_sender<__impl::__env>
- _Sender> // NOT TO SPEC
- requires stdexec::__tag_invocable_with_completion_scheduler<
- sync_wait_t, stdexec::set_value_t, _Sender>
+ template <__single_value_variant_sender<__env> _Sender> // NOT TO SPEC
+ requires __tag_invocable_with_completion_scheduler<sync_wait_t,
+ set_value_t, _Sender>
tag_invoke_result_t<
- sync_wait_t,
- stdexec::__completion_scheduler_for<_Sender, stdexec::set_value_t>,
- _Sender>
+ sync_wait_t, __completion_scheduler_for<_Sender, set_value_t>, _Sender>
operator()(_Sender&& __sndr) const
- noexcept(nothrow_tag_invocable<sync_wait_t,
- stdexec::__completion_scheduler_for<
- _Sender, stdexec::set_value_t>,
- _Sender>)
+ noexcept(nothrow_tag_invocable<
+ sync_wait_t, __completion_scheduler_for<_Sender, set_value_t>,
+ _Sender>)
{
- auto __sched =
- stdexec::get_completion_scheduler<stdexec::set_value_t>(__sndr);
+ auto __sched = get_completion_scheduler<set_value_t>(__sndr);
return tag_invoke(sync_wait_t{}, std::move(__sched),
(_Sender &&) __sndr);
}
// TODO: constrain on return type
- template <stdexec::__single_value_variant_sender<__impl::__env>
- _Sender> // NOT TO SPEC
- requires(!stdexec::__tag_invocable_with_completion_scheduler<
- sync_wait_t, stdexec::set_value_t, _Sender>) &&
+ template <__single_value_variant_sender<__env> _Sender> // NOT TO SPEC
+ requires(!__tag_invocable_with_completion_scheduler<
+ sync_wait_t, set_value_t, _Sender>) &&
tag_invocable<sync_wait_t, _Sender>
tag_invoke_result_t<sync_wait_t, _Sender> operator()(_Sender&& __sndr) const
noexcept(nothrow_tag_invocable<sync_wait_t, _Sender>)
@@ -6063,31 +6282,30 @@
return tag_invoke(sync_wait_t{}, (_Sender &&) __sndr);
}
- template <stdexec::__single_value_variant_sender<__impl::__env> _Sender>
- requires(!stdexec::__tag_invocable_with_completion_scheduler<
- sync_wait_t, stdexec::set_value_t, _Sender>) &&
+ template <__single_value_variant_sender<__env> _Sender>
+ requires(!__tag_invocable_with_completion_scheduler<
+ sync_wait_t, set_value_t, _Sender>) &&
(!tag_invocable<sync_wait_t, _Sender>) &&
- stdexec::sender<_Sender, __impl::__env> &&
- stdexec::sender_to<_Sender, __impl::__receiver<__x<_Sender>>>
+ sender<_Sender, __env> &&
+ sender_to<_Sender, __receiver_t<_Sender>>
auto operator()(_Sender&& __sndr) const
- -> std::optional<__impl::__sync_wait_result_t<_Sender>>
+ -> std::optional<__sync_wait_result_t<_Sender>>
{
- using state_t = __impl::__state<__x<_Sender>>;
+ using state_t = __sync_wait_result_impl<_Sender, __q<__state>>;
state_t __state{};
- stdexec::run_loop __loop;
+ run_loop __loop;
// Launch the sender with a continuation that will fill in a variant
// and notify a condition variable.
- auto __op_state = stdexec::connect(
- (_Sender &&) __sndr,
- __impl::__receiver<__x<_Sender>>{&__state, &__loop});
- stdexec::start(__op_state);
+ auto __op_state = connect((_Sender &&) __sndr,
+ __receiver_t<_Sender>{&__state, &__loop});
+ start(__op_state);
// Wait for the variant to be filled in.
__loop.run();
if (__state.__data_.index() == 2)
- rethrow_exception(std::get<2>(__state.__data_));
+ std::rethrow_exception(std::get<2>(__state.__data_));
if (__state.__data_.index() == 3)
return std::nullopt;
@@ -6100,38 +6318,33 @@
// [execution.senders.consumers.sync_wait_with_variant]
struct sync_wait_with_variant_t
{
- template <stdexec::sender<__impl::__env> _Sender>
- requires stdexec::__tag_invocable_with_completion_scheduler<
- sync_wait_with_variant_t, stdexec::set_value_t, _Sender>
- tag_invoke_result_t<
- sync_wait_with_variant_t,
- stdexec::__completion_scheduler_for<_Sender, stdexec::set_value_t>,
- _Sender>
+ template <sender<__env> _Sender>
+ requires __tag_invocable_with_completion_scheduler<
+ sync_wait_with_variant_t, set_value_t, _Sender>
+ tag_invoke_result_t<sync_wait_with_variant_t,
+ __completion_scheduler_for<_Sender, set_value_t>,
+ _Sender>
operator()(_Sender&& __sndr) const
- noexcept(nothrow_tag_invocable<sync_wait_with_variant_t,
- stdexec::__completion_scheduler_for<
- _Sender, stdexec::set_value_t>,
- _Sender>)
+ noexcept(nothrow_tag_invocable<
+ sync_wait_with_variant_t,
+ __completion_scheduler_for<_Sender, set_value_t>, _Sender>)
{
static_assert(
std::is_same_v<
- tag_invoke_result_t<sync_wait_with_variant_t,
- stdexec::__completion_scheduler_for<
- _Sender, stdexec::set_value_t>,
- _Sender>,
- std::optional<
- __impl::__sync_wait_with_variant_result_t<_Sender>>>,
- "The type of tag_invoke(stdexec::sync_wait_with_variant, stdexec::get_completion_scheduler, S) "
+ tag_invoke_result_t<
+ sync_wait_with_variant_t,
+ __completion_scheduler_for<_Sender, set_value_t>, _Sender>,
+ std::optional<__sync_wait_with_variant_result_t<_Sender>>>,
+ "The type of tag_invoke(sync_wait_with_variant, get_completion_scheduler, S) "
"must be sync-wait-with-variant-type<S, sync-wait-env>");
- auto __sched =
- stdexec::get_completion_scheduler<stdexec::set_value_t>(__sndr);
+ auto __sched = get_completion_scheduler<set_value_t>(__sndr);
return tag_invoke(sync_wait_with_variant_t{}, std::move(__sched),
(_Sender &&) __sndr);
}
- template <stdexec::sender<__impl::__env> _Sender>
- requires(!stdexec::__tag_invocable_with_completion_scheduler<
- sync_wait_with_variant_t, stdexec::set_value_t, _Sender>) &&
+ template <sender<__env> _Sender>
+ requires(!__tag_invocable_with_completion_scheduler<
+ sync_wait_with_variant_t, set_value_t, _Sender>) &&
tag_invocable<sync_wait_with_variant_t, _Sender>
tag_invoke_result_t<sync_wait_with_variant_t, _Sender>
operator()(_Sender&& __sndr) const
@@ -6140,22 +6353,21 @@
static_assert(
std::is_same_v<
tag_invoke_result_t<sync_wait_with_variant_t, _Sender>,
- std::optional<
- __impl::__sync_wait_with_variant_result_t<_Sender>>>,
- "The type of tag_invoke(stdexec::sync_wait_with_variant, S) "
+ std::optional<__sync_wait_with_variant_result_t<_Sender>>>,
+ "The type of tag_invoke(sync_wait_with_variant, S) "
"must be sync-wait-with-variant-type<S, sync-wait-env>");
return tag_invoke(sync_wait_with_variant_t{}, (_Sender &&) __sndr);
}
- template <stdexec::sender<__impl::__env> _Sender>
- requires(!stdexec::__tag_invocable_with_completion_scheduler<
- sync_wait_with_variant_t, stdexec::set_value_t, _Sender>) &&
+ template <sender<__env> _Sender>
+ requires(!__tag_invocable_with_completion_scheduler<
+ sync_wait_with_variant_t, set_value_t, _Sender>) &&
(!tag_invocable<sync_wait_with_variant_t, _Sender>) &&
- invocable<sync_wait_t, __impl::__into_variant_result_t<_Sender>>
- std::optional<__impl::__sync_wait_with_variant_result_t<_Sender>>
+ invocable<sync_wait_t, __into_variant_result_t<_Sender>>
+ std::optional<__sync_wait_with_variant_result_t<_Sender>>
operator()(_Sender&& __sndr) const
{
- return sync_wait_t{}(stdexec::into_variant((_Sender &&) __sndr));
+ return sync_wait_t{}(into_variant((_Sender &&) __sndr));
}
};
} // namespace __sync_wait
@@ -6171,4 +6383,4 @@
#pragma diagnostic pop
#endif
-_PRAGMA_POP()
+STDEXEC_PRAGMA_POP()
diff --git a/include/sdbusplus/async/stdexec/functional.hpp b/include/sdbusplus/async/stdexec/functional.hpp
index bcdb709..6893e6f 100644
--- a/include/sdbusplus/async/stdexec/functional.hpp
+++ b/include/sdbusplus/async/stdexec/functional.hpp
@@ -23,9 +23,9 @@
// A std::declval that doesn't instantiate templates:
#define _DECLVAL(...) ((static_cast<__VA_ARGS__ (*)() noexcept>(0))())
-namespace __std_concepts_polyfill
+namespace stdexec::__std_concepts
{
-#if __has_include(<concepts>) && __cpp_lib_concepts >= 202002
+#if STDEXEC_HAS_STD_CONCEPTS_HEADER()
using std::invocable;
#else
template <class _F, class... _As>
@@ -33,11 +33,11 @@
std::invoke((_F &&) __f, (_As &&) __as...);
};
#endif
-} // namespace __std_concepts_polyfill
+} // namespace stdexec::__std_concepts
namespace std
{
-using namespace __std_concepts_polyfill;
+using namespace stdexec::__std_concepts;
}
namespace stdexec
diff --git a/include/sdbusplus/async/stdexec/stop_token.hpp b/include/sdbusplus/async/stdexec/stop_token.hpp
index e17de00..6fd2719 100644
--- a/include/sdbusplus/async/stdexec/stop_token.hpp
+++ b/include/sdbusplus/async/stdexec/stop_token.hpp
@@ -300,12 +300,12 @@
__state_.store(__stop_requested_flag_, std::memory_order_release);
- bool removed_during_callback = false;
- __callbk->__removed_during_callback_ = &removed_during_callback;
+ bool __removed_during_callback = false;
+ __callbk->__removed_during_callback_ = &__removed_during_callback;
__callbk->__execute();
- if (!removed_during_callback)
+ if (!__removed_during_callback)
{
__callbk->__removed_during_callback_ = nullptr;
__callbk->__callback_completed_.store(true,
@@ -415,12 +415,12 @@
}
else
{
- auto notifying_thread = __notifying_thread_;
+ auto __notifying_thread = __notifying_thread_;
__unlock_(__old_state);
// Callback has either already been executed or is
// currently executing on another thread.
- if (std::this_thread::get_id() == notifying_thread)
+ if (std::this_thread::get_id() == __notifying_thread)
{
if (__callbk->__removed_during_callback_ != nullptr)
{
diff --git a/include/sdbusplus/async/stdexec/task.hpp b/include/sdbusplus/async/stdexec/task.hpp
index 5b25135..9bd59e9 100644
--- a/include/sdbusplus/async/stdexec/task.hpp
+++ b/include/sdbusplus/async/stdexec/task.hpp
@@ -26,8 +26,8 @@
#include <utility>
#include <variant>
-_PRAGMA_PUSH()
-_PRAGMA_IGNORE("-Wundefined-inline")
+STDEXEC_PRAGMA_PUSH()
+STDEXEC_PRAGMA_IGNORE("-Wundefined-inline")
namespace exec
{
@@ -239,6 +239,8 @@
struct __promise;
public:
+ using __t = basic_task;
+ using __id = basic_task;
using promise_type = __promise;
basic_task(basic_task&& __that) noexcept :
@@ -347,7 +349,7 @@
// Make this task awaitable within a particular context:
template <class _ParentPromise>
- requires std::constructible_from<
+ requires stdexec::constructible_from<
awaiter_context_t<__promise, _ParentPromise>, __promise&,
_ParentPromise&>
friend __task_awaitable<_ParentPromise> tag_invoke(stdexec::as_awaitable_t,
@@ -369,7 +371,7 @@
// the resulting list to __qf<set_value_t>, which uses the list of types
// as arguments of a function type. In other words, set_value_t() if _Ty
// is void, and set_value_t(_Ty) otherwise.
- using __set_value_sig_t = stdexec::__minvoke1<
+ using __set_value_sig_t = stdexec::__minvoke<
stdexec::__remove<void, stdexec::__qf<stdexec::set_value_t>>, _Ty>;
// Specify basic_task's completion signatures
@@ -405,4 +407,4 @@
using task = basic_task<_Ty, default_task_context<_Ty>>;
} // namespace exec
-_PRAGMA_POP()
+STDEXEC_PRAGMA_POP()
diff --git a/include/sdbusplus/async/timer.hpp b/include/sdbusplus/async/timer.hpp
index 23d8822..b957da3 100644
--- a/include/sdbusplus/async/timer.hpp
+++ b/include/sdbusplus/async/timer.hpp
@@ -95,14 +95,13 @@
return {self.ctx, self.time, std::move(r)};
}
- static auto sleep_for(context& ctx, event_t::time_resolution time)
+ static task<> sleep_for(context& ctx, event_t::time_resolution time)
{
// Run the delay sender and then switch back to the worker thread.
// The delay completion happens from the sd-event handler, which is
// ran on the 'caller' thread.
-
- return execution::when_all(sleep_sender(ctx, time),
- execution::schedule(get_scheduler(ctx)));
+ co_await sleep_sender(ctx, time);
+ co_await execution::schedule(get_scheduler(ctx));
}
private: