stdexec: update to latest commit
Signed-off-by: Patrick Williams <patrick@stwcx.xyz>
Change-Id: I8c34e20a8757c6d84a6151cfb9a5a9fd5b13c75a
diff --git a/include/sdbusplus/async/stdexec/__detail/__config.hpp b/include/sdbusplus/async/stdexec/__detail/__config.hpp
index 08e11ac..8772163 100644
--- a/include/sdbusplus/async/stdexec/__detail/__config.hpp
+++ b/include/sdbusplus/async/stdexec/__detail/__config.hpp
@@ -85,6 +85,27 @@
#define STDEXEC_HAS_BUILTIN(...) 0
#endif
+#if STDEXEC_HAS_BUILTIN(__is_trivially_copyable) || STDEXEC_MSVC()
+#define STDEXEC_IS_TRIVIALLY_COPYABLE(...) __is_trivially_copyable(__VA_ARGS__)
+#else
+#define STDEXEC_IS_TRIVIALLY_COPYABLE(...) \
+ std::is_trivially_copyable_v<__VA_ARGS__>
+#endif
+
+#if STDEXEC_HAS_BUILTIN(__is_base_of) || STDEXEC_MSVC()
+#define STDEXEC_IS_BASE_OF(...) __is_base_of(__VA_ARGS__)
+#else
+#define STDEXEC_IS_BASE_OF(...) std::is_base_of_v<__VA_ARGS__>
+#endif
+
+#if STDEXEC_HAS_BUILTIN(__is_convertible_to) || STDEXEC_MSVC()
+#define STDEXEC_IS_CONVERTIBLE_TO(...) __is_convertible_to(__VA_ARGS__)
+#elif STDEXEC_HAS_BUILTIN(__is_convertible)
+#define STDEXEC_IS_CONVERTIBLE_TO(...) __is_convertible(__VA_ARGS__)
+#else
+#define STDEXEC_IS_CONVERTIBLE_TO(...) std::is_convertible_v<__VA_ARGS__>
+#endif
+
// Before gcc-12, gcc really didn't like tuples or variants of immovable types
#if STDEXEC_GCC() && (__GNUC__ < 12)
#define STDEXEC_IMMOVABLE(_XP) _XP(_XP&&)
diff --git a/include/sdbusplus/async/stdexec/__detail/__type_traits.hpp b/include/sdbusplus/async/stdexec/__detail/__type_traits.hpp
index 260cdc7..93e303a 100644
--- a/include/sdbusplus/async/stdexec/__detail/__type_traits.hpp
+++ b/include/sdbusplus/async/stdexec/__detail/__type_traits.hpp
@@ -27,7 +27,7 @@
//////////////////////////////////////////////////////////////////////////////////////////////////
// __decay_t: An efficient implementation for std::decay
-#if __has_builtin(__decay)
+#if STDEXEC_HAS_BUILTIN(__decay)
template <class _Ty>
using __decay_t = __decay(_Ty);
diff --git a/include/sdbusplus/async/stdexec/any_sender_of.hpp b/include/sdbusplus/async/stdexec/any_sender_of.hpp
index ac7541b..fdadae7 100644
--- a/include/sdbusplus/async/stdexec/any_sender_of.hpp
+++ b/include/sdbusplus/async/stdexec/any_sender_of.hpp
@@ -295,14 +295,163 @@
class __t;
};
+template <class _Vtable, class _Allocator,
+ std::size_t _Alignment = alignof(std::max_align_t),
+ std::size_t _InlineSize = 3 * sizeof(void*)>
+struct __immovable_storage
+{
+ class __t : __immovable
+ {
+ static constexpr std::size_t __buffer_size = std::max(_InlineSize,
+ sizeof(void*));
+ static constexpr std::size_t __alignment = std::max(_Alignment,
+ alignof(void*));
+ using __with_delete = __delete_t(void() noexcept);
+ using __vtable_t = __storage_vtable<_Vtable, __with_delete>;
+
+ template <class _Tp>
+ static constexpr bool __is_small = sizeof(_Tp) <= __buffer_size &&
+ alignof(_Tp) <= __alignment;
+
+ template <class _Tp>
+ static constexpr const __vtable_t* __get_vtable_of_type() noexcept
+ {
+ return &__storage_vtbl<__t, __decay_t<_Tp>, _Vtable, __with_delete>;
+ }
+
+ public:
+ using __id = __immovable_storage;
+
+ __t() = default;
+
+ template <__not_decays_to<__t> _Tp>
+ requires __callable<__create_vtable_t, __mtype<_Vtable>,
+ __mtype<__decay_t<_Tp>>>
+ __t(_Tp&& __object) : __vtable_{__get_vtable_of_type<_Tp>()}
+ {
+ using _Dp = __decay_t<_Tp>;
+ if constexpr (__is_small<_Dp>)
+ {
+ __construct_small<_Dp>((_Tp&&)__object);
+ }
+ else
+ {
+ __construct_large<_Dp>((_Tp&&)__object);
+ }
+ }
+
+ template <class _Tp, class... _Args>
+ requires __callable<__create_vtable_t, __mtype<_Vtable>,
+ __mtype<_Tp>>
+ __t(std::in_place_type_t<_Tp>, _Args&&... __args) :
+ __vtable_{__get_vtable_of_type<_Tp>()}
+ {
+ if constexpr (__is_small<_Tp>)
+ {
+ __construct_small<_Tp>((_Args&&)__args...);
+ }
+ else
+ {
+ __construct_large<_Tp>((_Args&&)__args...);
+ }
+ }
+
+ ~__t()
+ {
+ __reset();
+ }
+
+ void __reset() noexcept
+ {
+ (*__vtable_)(__delete, this);
+ __object_pointer_ = nullptr;
+ __vtable_ = __default_storage_vtable((__vtable_t*)nullptr);
+ }
+
+ const _Vtable* __get_vtable() const noexcept
+ {
+ return __vtable_;
+ }
+
+ void* __get_object_pointer() const noexcept
+ {
+ return __object_pointer_;
+ }
+
+ private:
+ template <class _Tp, class... _As>
+ void __construct_small(_As&&... __args)
+ {
+ static_assert(sizeof(_Tp) <= __buffer_size &&
+ alignof(_Tp) <= __alignment);
+ _Tp* __pointer =
+ static_cast<_Tp*>(static_cast<void*>(&__buffer_[0]));
+ using _Alloc = typename std::allocator_traits<
+ _Allocator>::template rebind_alloc<_Tp>;
+ _Alloc __alloc{__allocator_};
+ std::allocator_traits<_Alloc>::construct(__alloc, __pointer,
+ (_As&&)__args...);
+ __object_pointer_ = __pointer;
+ }
+
+ template <class _Tp, class... _As>
+ void __construct_large(_As&&... __args)
+ {
+ using _Alloc = typename std::allocator_traits<
+ _Allocator>::template rebind_alloc<_Tp>;
+ _Alloc __alloc{__allocator_};
+ _Tp* __pointer = std::allocator_traits<_Alloc>::allocate(__alloc,
+ 1);
+ try
+ {
+ std::allocator_traits<_Alloc>::construct(__alloc, __pointer,
+ (_As&&)__args...);
+ }
+ catch (...)
+ {
+ std::allocator_traits<_Alloc>::deallocate(__alloc, __pointer,
+ 1);
+ throw;
+ }
+ __object_pointer_ = __pointer;
+ }
+
+ template <class _Tp>
+ friend void tag_invoke(__delete_t, __mtype<_Tp>, __t& __self) noexcept
+ {
+ if (!__self.__object_pointer_)
+ {
+ return;
+ }
+ using _Alloc = typename std::allocator_traits<
+ _Allocator>::template rebind_alloc<_Tp>;
+ _Alloc __alloc{__self.__allocator_};
+ _Tp* __pointer = static_cast<_Tp*>(
+ std::exchange(__self.__object_pointer_, nullptr));
+ std::allocator_traits<_Alloc>::destroy(__alloc, __pointer);
+ if constexpr (!__is_small<_Tp>)
+ {
+ std::allocator_traits<_Alloc>::deallocate(__alloc, __pointer,
+ 1);
+ }
+ }
+
+ private:
+ const __vtable_t* __vtable_{
+ __default_storage_vtable((__vtable_t*)nullptr)};
+ void* __object_pointer_{nullptr};
+ alignas(__alignment) std::byte __buffer_[__buffer_size]{};
+ STDEXEC_NO_UNIQUE_ADDRESS _Allocator __allocator_{};
+ };
+};
+
template <class _Vtable, class _Allocator, bool _Copyable,
std::size_t _Alignment, std::size_t _InlineSize>
class __storage<_Vtable, _Allocator, _Copyable, _Alignment, _InlineSize>::__t :
__if_c<_Copyable, __, __move_only>
{
- static_assert(
- std::is_convertible_v<
- typename std::allocator_traits<_Allocator>::void_pointer, void*>);
+ static_assert(STDEXEC_IS_CONVERTIBLE_TO(
+ typename std::allocator_traits<_Allocator>::void_pointer, void*));
static constexpr std::size_t __buffer_size = std::max(_InlineSize,
sizeof(void*));
@@ -529,12 +678,47 @@
STDEXEC_NO_UNIQUE_ADDRESS _Allocator __allocator_{};
};
+struct __empty_vtable
+{
+ template <class _Sender>
+ friend const __empty_vtable* tag_invoke(__create_vtable_t,
+ __mtype<__empty_vtable>,
+ __mtype<_Sender>) noexcept
+ {
+ static const __empty_vtable __vtable_{};
+ return &__vtable_;
+ }
+};
+
+template <class _VTable = __empty_vtable,
+ class _Allocator = std::allocator<std::byte>>
+using __immovable_storage_t = __t<__immovable_storage<_VTable, _Allocator>>;
+
template <class _VTable, class _Allocator = std::allocator<std::byte>>
using __unique_storage_t = __t<__storage<_VTable, _Allocator>>;
template <class _VTable, class _Allocator = std::allocator<std::byte>>
using __copyable_storage_t = __t<__storage<_VTable, _Allocator, true>>;
+template <class _Tag, class... _As>
+_Tag __tag_type(_Tag (*)(_As...));
+
+template <class _Tag, class... _As>
+_Tag __tag_type(_Tag (*)(_As...) noexcept);
+
+template <class _Query>
+concept __is_stop_token_query = requires {
+ {
+ __tag_type(static_cast<_Query>(nullptr))
+ } -> same_as<get_stop_token_t>;
+ };
+
+template <class _Query>
+concept __is_not_stop_token_query = !__is_stop_token_query<_Query>;
+
+template <class _Query>
+using __is_not_stop_token_query_v = __mbool<__is_not_stop_token_query<_Query>>;
+
namespace __rec
{
template <class _Sig>
@@ -592,11 +776,87 @@
};
template <class... _Sigs, class... _Queries>
+ requires(__is_not_stop_token_query<_Queries> && ...)
struct __ref<completion_signatures<_Sigs...>, _Queries...>
{
private:
using __vtable_t =
- __t<__vtable<completion_signatures<_Sigs...>, _Queries...>>;
+ stdexec::__t<__vtable<completion_signatures<_Sigs...>, _Queries...>>;
+
+ struct __env_t
+ {
+ const __vtable_t* __vtable_;
+ void* __rcvr_;
+ in_place_stop_token __token_;
+
+ template <class _Tag, class... _As>
+ requires __callable<const __vtable_t&, _Tag, void*, _As...>
+ friend auto
+ tag_invoke(_Tag, const __env_t& __self, _As&&... __as) noexcept(
+ __nothrow_callable<const __vtable_t&, _Tag, void*, _As...>)
+ -> __call_result_t<const __vtable_t&, _Tag, void*, _As...>
+ {
+ return (*__self.__vtable_)(_Tag{}, __self.__rcvr_, (_As&&)__as...);
+ }
+
+ friend in_place_stop_token tag_invoke(get_stop_token_t,
+ const __env_t& __self) noexcept
+ {
+ return __self.__token_;
+ }
+ } __env_;
+
+ public:
+ using is_receiver = void;
+ using __id = __ref;
+ using __t = __ref;
+
+ template <__none_of<__ref, const __ref, __env_t, const __env_t> _Rcvr>
+ requires receiver_of<_Rcvr, completion_signatures<_Sigs...>> &&
+ (__callable<__query_vfun_fn<_Rcvr>, _Queries> && ...)
+ __ref(_Rcvr& __rcvr) noexcept :
+ __env_{__create_vtable(__mtype<__vtable_t>{}, __mtype<_Rcvr>{}),
+ &__rcvr, stdexec::get_stop_token(stdexec::get_env(__rcvr))}
+ {}
+
+ template <__completion_tag _Tag, __decays_to<__ref> _Self, class... _As>
+ requires __one_of<_Tag(_As...), _Sigs...>
+ friend void tag_invoke(_Tag, _Self&& __self, _As&&... __as) noexcept
+ {
+ (*static_cast<const __rcvr_vfun<_Tag(_As...)>*>(__self.__env_.__vtable_)
+ ->__fn_)(((_Self&&)__self).__env_.__rcvr_, (_As&&)__as...);
+ }
+
+ template <std::same_as<__ref> Self>
+ friend const __env_t& tag_invoke(get_env_t, const Self& __self) noexcept
+ {
+ return __self.__env_;
+ }
+};
+
+__mbool<true> __test_never_stop_token(
+ get_stop_token_t (*)(never_stop_token (*)() noexcept));
+
+template <class _Tag, class _Ret, class... _As>
+__mbool<false> __test_never_stop_token(_Tag (*)(_Ret (*)(_As...) noexcept));
+
+template <class _Tag, class _Ret, class... _As>
+__mbool<false> __test_never_stop_token(_Tag (*)(_Ret (*)(_As...)));
+
+template <class _Query>
+using __is_never_stop_token_query =
+ decltype(__test_never_stop_token(static_cast<_Query>(nullptr)));
+
+template <class... _Sigs, class... _Queries>
+ requires(__is_stop_token_query<_Queries> || ...)
+struct __ref<completion_signatures<_Sigs...>, _Queries...>
+{
+ private:
+ using _FilteredQueries =
+ __minvoke<__remove_if<__q<__is_never_stop_token_query>>, _Queries...>;
+ using __vtable_t = stdexec::__t<
+ __mapply<__mbind_front_q<__vtable, completion_signatures<_Sigs...>>,
+ _FilteredQueries>>;
struct __env_t
{
@@ -616,6 +876,8 @@
public:
using is_receiver = void;
+ using __id = __ref;
+ using __t = __ref;
template <__none_of<__ref, const __ref, __env_t, const __env_t> _Rcvr>
requires receiver_of<_Rcvr, completion_signatures<_Sigs...>> &&
@@ -663,59 +925,141 @@
}
};
-using __unique_operation_storage = __unique_storage_t<__operation_vtable>;
+using __immovable_operation_storage = __immovable_storage_t<__operation_vtable>;
template <class _Sigs, class _Queries>
using __receiver_ref =
__mapply<__mbind_front<__q<__rec::__ref>, _Sigs>, _Queries>;
-template <class _Receiver, class _Sigs, class _Queries>
-struct __operation_base
+struct __on_stop_t
{
- STDEXEC_NO_UNIQUE_ADDRESS _Receiver __receiver_;
+ stdexec::in_place_stop_source& __source_;
+
+ void operator()() const noexcept
+ {
+ __source_.request_stop();
+ }
};
-template <class _Sender, class _Receiver, class _Queries>
-struct __operation
+template <class _Receiver>
+struct __operation_base
{
- using _Sigs = completion_signatures_of_t<_Sender>;
- using __receiver_ref_t = __receiver_ref<_Sigs, _Queries>;
+ STDEXEC_NO_UNIQUE_ADDRESS _Receiver __rcvr_;
+ stdexec::in_place_stop_source __stop_source_{};
+ using __stop_callback = typename stdexec::stop_token_of_t<
+ stdexec::env_of_t<_Receiver>>::template callback_type<__on_stop_t>;
+ std::optional<__stop_callback> __on_stop_{};
+};
- struct __rec
+template <class _Env>
+using __env_t =
+ __make_env_t<_Env, __with<get_stop_token_t, in_place_stop_token>>;
+
+template <class _ReceiverId>
+struct __stoppable_receiver
+{
+ using _Receiver = stdexec::__t<_ReceiverId>;
+
+ struct __t
{
- using is_receiver = void;
- __operation_base<_Receiver, _Sigs, _Queries>* __op_;
+ __operation_base<_Receiver>* __op_;
- template <__completion_tag _CPO, __decays_to<__rec> _Self,
+ template <same_as<set_value_t> _SetValue, same_as<__t> _Self,
class... _Args>
- requires __callable<_CPO, _Receiver&&, _Args...>
- friend void tag_invoke(_CPO, _Self&& __self, _Args&&... __args) noexcept
+ requires __callable<_SetValue, _Receiver&&, _Args...>
+ friend void tag_invoke(_SetValue, _Self&& __self,
+ _Args&&... __args) noexcept
{
- _CPO{}((_Receiver&&)__self.__op_->__receiver_, (_Args&&)__args...);
+ __self.__op_->__on_stop_.reset();
+ _SetValue{}(static_cast<_Receiver&&>(__self.__op_->__rcvr_),
+ static_cast<_Args&&>(__args)...);
}
- friend env_of_t<_Receiver> tag_invoke(get_env_t,
- const __rec& __self) noexcept
+ template <same_as<set_error_t> _SetError, same_as<__t> _Self,
+ class _Error>
+ requires __callable<_SetError, _Receiver&&, _Error>
+ friend void tag_invoke(_SetError, _Self&& __self,
+ _Error&& __err) noexcept
{
- return get_env(__self.__op_->__receiver_);
+ __self.__op_->__on_stop_.reset();
+ _SetError{}(static_cast<_Receiver&&>(__self.__op_->__rcvr_),
+ static_cast<_Error&&>(__err));
+ }
+
+ template <same_as<set_stopped_t> _SetStopped, same_as<__t> _Self>
+ requires __callable<_SetStopped, _Receiver&&>
+ friend void tag_invoke(_SetStopped, _Self&& __self) noexcept
+ {
+ __self.__op_->__on_stop_.reset();
+ _SetStopped{}(static_cast<_Receiver&&>(__self.__op_->__rcvr_));
+ }
+
+ template <same_as<get_env_t> _GetEnv, same_as<__t> _Self>
+ friend __env_t<env_of_t<_Receiver>>
+ tag_invoke(_GetEnv, const _Self& __self) noexcept
+ {
+ return __make_env(
+ get_env(__self.__op_->__rcvr_),
+ __with_(get_stop_token,
+ __self.__op_->__stop_source_.get_token()));
}
};
+};
- class __t : __immovable, __operation_base<_Receiver, _Sigs, _Queries>
+template <class _ReceiverId>
+using __stoppable_receiver_t = stdexec::__t<__stoppable_receiver<_ReceiverId>>;
+
+template <class _ReceiverId, bool>
+struct __operation
+{
+ using _Receiver = stdexec::__t<_ReceiverId>;
+
+ class __t : public __operation_base<_Receiver>
{
public:
using __id = __operation;
+ template <class _Sender>
__t(_Sender&& __sender, _Receiver&& __receiver) :
- __operation_base<_Receiver, _Sigs, _Queries>{
- (_Receiver&&)__receiver},
- __storage_{__sender.__connect(__receiver_ref_t{__rec_})}
+ __operation_base<_Receiver>{static_cast<_Receiver&&>(__receiver)},
+ __rec_{this}, __storage_{__sender.__connect(__rec_)}
{}
private:
- __rec __rec_{
- static_cast<__operation_base<_Receiver, _Sigs, _Queries>*>(this)};
- __unique_operation_storage __storage_{};
+ __stoppable_receiver_t<_ReceiverId> __rec_;
+ __immovable_operation_storage __storage_{};
+
+ friend void tag_invoke(start_t, __t& __self) noexcept
+ {
+ __self.__on_stop_.emplace(
+ stdexec::get_stop_token(stdexec::get_env(__self.__rcvr_)),
+ __on_stop_t{__self.__stop_source_});
+ STDEXEC_ASSERT(__self.__storage_.__get_vtable()->__start_);
+ __self.__storage_.__get_vtable()->__start_(
+ __self.__storage_.__get_object_pointer());
+ }
+ };
+};
+
+template <class _ReceiverId>
+struct __operation<_ReceiverId, false>
+{
+ using _Receiver = stdexec::__t<_ReceiverId>;
+
+ class __t
+ {
+ public:
+ using __id = __operation;
+
+ template <class _Sender>
+ __t(_Sender&& __sender, _Receiver&& __receiver) :
+ __rec_{static_cast<_Receiver&&>(__receiver)},
+ __storage_{__sender.__connect(__rec_)}
+ {}
+
+ private:
+ STDEXEC_NO_UNIQUE_ADDRESS _Receiver __rec_;
+ __immovable_operation_storage __storage_{};
friend void tag_invoke(start_t, __t& __self) noexcept
{
@@ -753,6 +1097,9 @@
struct __sender
{
using __receiver_ref_t = __receiver_ref<_Sigs, _ReceiverQueries>;
+ static constexpr bool __with_in_place_stop_token =
+ __v<__mapply<__mall_of<__q<__is_not_stop_token_query_v>>,
+ _ReceiverQueries>>;
class __vtable : public __query_vtable<_SenderQueries>
{
@@ -764,7 +1111,7 @@
return *this;
}
- __unique_operation_storage (*__connect_)(void*, __receiver_ref_t);
+ __immovable_operation_storage (*__connect_)(void*, __receiver_ref_t);
private:
template <sender_to<__receiver_ref_t> _Sender>
@@ -774,16 +1121,17 @@
static const __vtable __vtable_{
{*__create_vtable(__mtype<__query_vtable<_SenderQueries>>{},
__mtype<_Sender>{})},
- [](void* __object_pointer,
- __receiver_ref_t __receiver) -> __unique_operation_storage {
+ [](void* __object_pointer, __receiver_ref_t __receiver)
+ -> __immovable_operation_storage {
_Sender& __sender =
*static_cast<_Sender*>(__object_pointer);
using __op_state_t =
connect_result_t<_Sender, __receiver_ref_t>;
- return __unique_operation_storage{
+ return __immovable_operation_storage{
std::in_place_type<__op_state_t>, __conv{[&] {
- return connect((_Sender&&)__sender,
- (__receiver_ref_t&&)__receiver);
+ return stdexec::connect(
+ (_Sender&&)__sender,
+ (__receiver_ref_t&&)__receiver);
}}};
}};
return &__vtable_;
@@ -834,7 +1182,7 @@
__t(_Sender&& __sndr) : __storage_{(_Sender&&)__sndr}
{}
- __unique_operation_storage __connect(__receiver_ref_t __receiver)
+ __immovable_operation_storage __connect(__receiver_ref_t __receiver)
{
return __storage_.__get_vtable()->__connect_(
__storage_.__get_object_pointer(),
@@ -850,8 +1198,8 @@
__unique_storage_t<__vtable> __storage_;
template <receiver_of<_Sigs> _Rcvr>
- friend stdexec::__t<
- __operation<__t, __decay_t<_Rcvr>, _ReceiverQueries>>
+ friend stdexec::__t<__operation<stdexec::__id<__decay_t<_Rcvr>>,
+ __with_in_place_stop_token>>
tag_invoke(connect_t, __t&& __self, _Rcvr&& __rcvr)
{
return {(__t&&)__self, (_Rcvr&&)__rcvr};
@@ -903,8 +1251,8 @@
return __sender_t{schedule(__scheduler)};
},
[](const void* __self, const void* __other) noexcept -> bool {
- static_assert(noexcept(std::declval<const _Scheduler&>() ==
- std::declval<const _Scheduler&>()));
+ static_assert(noexcept(__declval<const _Scheduler&>() ==
+ __declval<const _Scheduler&>()));
STDEXEC_ASSERT(__self && __other);
const _Scheduler& __self_scheduler =
*static_cast<const _Scheduler*>(__self);
@@ -1026,9 +1374,8 @@
using completion_signatures =
typename __sender_base::completion_signatures;
- template <class _Sender>
- requires(!stdexec::__decays_to<_Sender, any_sender>) &&
- stdexec::sender<_Sender>
+ template <stdexec::__not_decays_to<any_sender> _Sender>
+ requires stdexec::sender_to<_Sender, __receiver_base>
any_sender(_Sender&& __sender) noexcept(
stdexec::__nothrow_constructible_from<__sender_base, _Sender>) :
__sender_((_Sender&&)__sender)
diff --git a/include/sdbusplus/async/stdexec/async_scope.hpp b/include/sdbusplus/async/stdexec/async_scope.hpp
index 1f84717..12a19db 100644
--- a/include/sdbusplus/async/stdexec/async_scope.hpp
+++ b/include/sdbusplus/async/stdexec/async_scope.hpp
@@ -74,7 +74,7 @@
explicit __when_empty_op(const __impl* __scope, _Constrained&& __sndr,
_Receiver __rcvr) :
__task{{}, __scope, __notify_waiter},
- __op_(connect((_Constrained&&)__sndr, (_Receiver&&)__rcvr))
+ __op_(stdexec::connect((_Constrained&&)__sndr, (_Receiver&&)__rcvr))
{}
private:
@@ -156,6 +156,7 @@
template <class _ReceiverId>
struct __nest_rcvr
{
+ using is_receiver = void;
using _Receiver = __t<_ReceiverId>;
__nest_op_base<_ReceiverId>* __op_;
@@ -210,7 +211,7 @@
template <__decays_to<_Constrained> _Sender, __decays_to<_Receiver> _Rcvr>
explicit __nest_op(const __impl* __scope, _Sender&& __c, _Rcvr&& __rcvr) :
__nest_op_base<_ReceiverId>{{}, __scope, (_Rcvr&&)__rcvr},
- __op_(connect((_Sender&&)__c, __nest_rcvr<_ReceiverId>{this}))
+ __op_(stdexec::connect((_Sender&&)__c, __nest_rcvr<_ReceiverId>{this}))
{}
private:
@@ -549,6 +550,7 @@
template <class _CompletionsId, class _EnvId>
struct __future_rcvr
{
+ using is_receiver = void;
using _Completions = __t<_CompletionsId>;
using _Env = __t<_EnvId>;
__future_state_base<_Completions, _Env>* __state_;
@@ -617,8 +619,9 @@
__future_state(_Sender __sndr, _Env __env, const __impl* __scope) :
__future_state_base<_Completions, _Env>((_Env&&)__env, __scope),
- __op_(connect((_Sender&&)__sndr,
- __future_receiver_t<_Sender, _Env>{this, __scope}))
+ __op_(
+ stdexec::connect((_Sender&&)__sndr,
+ __future_receiver_t<_Sender, _Env>{this, __scope}))
{}
connect_result_t<_Sender, __future_receiver_t<_Sender, _Env>> __op_;
@@ -707,6 +710,7 @@
template <class _EnvId>
struct __spawn_rcvr
{
+ using is_receiver = void;
using _Env = __t<_EnvId>;
__spawn_op_base<_EnvId>* __op_;
const __impl* __scope_;
@@ -749,7 +753,8 @@
[](__spawn_op_base<_EnvId>* __op) {
delete static_cast<__spawn_op*>(__op);
}},
- __op_(connect((_Sndr&&)__sndr, __spawn_receiver_t<_Env>{this, __scope}))
+ __op_(stdexec::connect((_Sndr&&)__sndr,
+ __spawn_receiver_t<_Env>{this, __scope}))
{}
void __start_() noexcept
diff --git a/include/sdbusplus/async/stdexec/at_coroutine_exit.hpp b/include/sdbusplus/async/stdexec/at_coroutine_exit.hpp
index c32f3af..dc6df2e 100644
--- a/include/sdbusplus/async/stdexec/at_coroutine_exit.hpp
+++ b/include/sdbusplus/async/stdexec/at_coroutine_exit.hpp
@@ -44,6 +44,7 @@
{
struct __t
{
+ using is_receiver = void;
using __id = __receiver_id;
_Receiver __receiver_;
@@ -92,8 +93,9 @@
friend connect_result_t<_Sender, __receiver<_Receiver>>
tag_invoke(connect_t, __t&& __self, _Receiver&& __rcvr) noexcept
{
- return connect((_Sender&&)__self.__sender_,
- __receiver<_Receiver>{(_Receiver&&)__rcvr});
+ return stdexec::connect(
+ (_Sender&&)__self.__sender_,
+ __receiver<_Receiver>{(_Receiver&&)__rcvr});
}
template <__decays_to<__t> _Self, class _Env>
diff --git a/include/sdbusplus/async/stdexec/commit.info b/include/sdbusplus/async/stdexec/commit.info
index 6031367..6c3c5cd 100644
--- a/include/sdbusplus/async/stdexec/commit.info
+++ b/include/sdbusplus/async/stdexec/commit.info
@@ -1 +1 @@
-b790506e622afd3c945b2319d254cbfa301c0c9e
+f1409100e46d3bdf2cbf2d6fb6c8e4a96e8bd307
diff --git a/include/sdbusplus/async/stdexec/concepts.hpp b/include/sdbusplus/async/stdexec/concepts.hpp
index b64a95a..3098123 100644
--- a/include/sdbusplus/async/stdexec/concepts.hpp
+++ b/include/sdbusplus/async/stdexec/concepts.hpp
@@ -56,13 +56,13 @@
concept integral = std::is_integral_v<T>;
template <class _Ap, class _Bp>
-concept derived_from = //
- std::is_base_of_v<_Bp, _Ap> && //
- std::is_convertible_v<const volatile _Ap*, const volatile _Bp*>;
+concept derived_from = //
+ STDEXEC_IS_BASE_OF(_Bp, _Ap) && //
+ STDEXEC_IS_CONVERTIBLE_TO(const volatile _Ap*, const volatile _Bp*);
template <class _From, class _To>
-concept convertible_to = //
- std::is_convertible_v<_From, _To> && //
+concept convertible_to = //
+ STDEXEC_IS_CONVERTIBLE_TO(_From, _To) && //
requires(_From (&__fun)()) { static_cast<_To>(__fun()); };
template <class _Ty>
diff --git a/include/sdbusplus/async/stdexec/env.hpp b/include/sdbusplus/async/stdexec/env.hpp
index 1ec7a6e..0beaf08 100644
--- a/include/sdbusplus/async/stdexec/env.hpp
+++ b/include/sdbusplus/async/stdexec/env.hpp
@@ -187,7 +187,7 @@
__operation(_Sender&& __sndr, auto&& __rcvr, auto&& __env) :
__base_t{(decltype(__rcvr))__rcvr, (decltype(__env))__env},
- __state_{connect((_Sender&&)__sndr, __receiver_t{{}, this})}
+ __state_{stdexec::connect((_Sender&&)__sndr, __receiver_t{{}, this})}
{}
friend void tag_invoke(start_t, __operation& __self) noexcept
@@ -200,7 +200,6 @@
struct __sender
{
using _Sender = stdexec::__t<_SenderId>;
- using is_sender = void;
template <class _Receiver>
using __receiver_t = stdexec::__t<__receiver<__id<_Receiver>, _Env>>;
@@ -210,6 +209,7 @@
struct __t
{
+ using is_sender = void;
using __id = __sender;
_Sender __sndr_;
_Env __env_;
diff --git a/include/sdbusplus/async/stdexec/execution.hpp b/include/sdbusplus/async/stdexec/execution.hpp
index 36e85bd..981de5d 100644
--- a/include/sdbusplus/async/stdexec/execution.hpp
+++ b/include/sdbusplus/async/stdexec/execution.hpp
@@ -44,20 +44,39 @@
#pragma diag_suppress type_qualifiers_ignored_on_reference
#endif
-#ifdef STDEXEC_ENABLE_R5_DEPRECATIONS
-#define STDEXEC_R5_SENDER_DEPR_WARNING \
- [[deprecated( \
- "Deprecated sender type detected. Please update the type to satisfy the boolean " \
- "stdexec::enable_sender<S> trait. " \
- "Defining a member type alias named 'is_sender' is one way to do this.")]]
-#define STDEXEC_R5_RECEIVER_DEPR_WARNING \
- [[deprecated( \
- "Deprecated receiver type detected. Please update the type for to satisfy the boolean " \
- "stdexec::enable_receiver<R> trait. Defining a member type alias named 'is_receiver' is one " \
- "way to do this.")]]
+#ifndef STDEXEC_DISABLE_R5_DEPRECATION_WARNINGS
+#define STDEXEC_R5_SENDER_DEPRECATION_WARNING \
+ [[deprecated( \
+ "Deprecated sender type detected. " \
+ "Please give the type a nested `is_sender` type alias, or " \
+ "specialize stdexec::enable_sender<your-sender-type> to be `true`. " \
+ "To suppress this deprecation warning, define `STDEXEC_DISABLE_R5_DEPRECATIONS`.")]]
+#define STDEXEC_R5_RECEIVER_DEPRECATION_WARNING \
+ [[deprecated( \
+ "Deprecated receiver type detected. " \
+ "Please give the type a nested `is_receiver` type alias, or " \
+ "specialize stdexec::enable_receiver<your-receiver-type> to be `true`." \
+ "To suppress this deprecation warning, define `STDEXEC_DISABLE_R5_DEPRECATIONS`.")]]
+#define STDEXEC_R5_DEPENDENT_COMPLETION_SIGNATURES_DEPRECATION_WARNING \
+ [[deprecated( \
+ "The `dependent_completion_signatures<>` type is deprecated. There is " \
+ "no need to define a customization of `get_completion_signatures` for " \
+ "sender types whose completions are dependent on the receiver's environment. " \
+ "Give your sender type a nested `is_sender` type alias instead, " \
+ "specialize stdexec::enable_sender<your-sender-type> to be `true`. " \
+ "To suppress this deprecation warning, define `STDEXEC_DISABLE_R5_DEPRECATIONS`.")]]
+#define STDEXEC_R5_NO_ENV_DEPRECATION_WARNING \
+ [[deprecated( \
+ "The `no_env` type is deprecated. The stdexec library no longer needs to use " \
+ "it to probe a type for satisfaction of the `sender` concept. " \
+ "Give your sender type a nested `is_sender` type alias instead, or " \
+ "specialize stdexec::enable_sender<your-sender-type> to be `true`. " \
+ "To suppress this deprecation warning, define `STDEXEC_DISABLE_R5_DEPRECATIONS`.")]]
#else
-#define STDEXEC_R5_SENDER_DEPR_WARNING
-#define STDEXEC_R5_RECEIVER_DEPR_WARNING
+#define STDEXEC_R5_SENDER_DEPRECATION_WARNING
+#define STDEXEC_R5_RECEIVER_DEPRECATION_WARNING
+#define STDEXEC_R5_DEPENDENT_COMPLETION_SIGNATURES_DEPRECATION_WARNING
+#define STDEXEC_R5_NO_ENV_DEPRECATION_WARNING
#endif
#define STDEXEC_LEGACY_R5_CONCEPTS() 1
@@ -297,8 +316,20 @@
inline constexpr get_delegatee_scheduler_t get_delegatee_scheduler{};
inline constexpr get_allocator_t get_allocator{};
inline constexpr get_stop_token_t get_stop_token{};
+#if !STDEXEC_GCC() || defined(__OPTIMIZE__)
template <__completion_tag _CPO>
inline constexpr get_completion_scheduler_t<_CPO> get_completion_scheduler{};
+#else
+template <>
+inline constexpr get_completion_scheduler_t<set_value_t>
+ get_completion_scheduler<set_value_t>{};
+template <>
+inline constexpr get_completion_scheduler_t<set_error_t>
+ get_completion_scheduler<set_error_t>{};
+template <>
+inline constexpr get_completion_scheduler_t<set_stopped_t>
+ get_completion_scheduler<set_stopped_t>{};
+#endif
template <class _Tag>
concept __forwarding_query = forwarding_query(_Tag{});
@@ -353,10 +384,10 @@
STDEXEC_NO_UNIQUE_ADDRESS _Env __env_;
template <__forwarding_query _Tag>
- requires __callable<_Tag, const _Env&>
+ requires tag_invocable<_Tag, const _Env&>
friend auto tag_invoke(_Tag, const __env_fwd& __self) //
- noexcept(__nothrow_callable<_Tag, const _Env&>)
- -> __call_result_t<_Tag, const _Env&>
+ noexcept(nothrow_tag_invocable<_Tag, const _Env&>)
+ -> tag_invoke_result_t<_Tag, const _Env&>
{
return _Tag()(__self.__env_);
}
@@ -376,10 +407,10 @@
}
template <class _Tag>
- requires __callable<_Tag, const _Env&>
+ requires tag_invocable<_Tag, const _Env&>
friend auto tag_invoke(_Tag, const __env_join& __self) //
- noexcept(__nothrow_callable<_Tag, const _Env&>)
- -> __call_result_t<_Tag, const _Env&>
+ noexcept(nothrow_tag_invocable<_Tag, const _Env&>)
+ -> tag_invoke_result_t<_Tag, const _Env&>
{
return _Tag()(__self.__env_);
}
@@ -841,9 +872,17 @@
/////////////////////////////////////////////////////////////////////////////
// [execution.receivers]
+struct __receiver_base
+{};
+
template <class _Receiver>
-inline constexpr bool enable_receiver = //
- requires { typename _Receiver::is_receiver; };
+concept __enable_receiver = //
+ requires { typename _Receiver::is_receiver; } ||
+ STDEXEC_IS_BASE_OF(__receiver_base, _Receiver);
+
+template <class _Receiver>
+inline constexpr bool enable_receiver =
+ __enable_receiver<_Receiver>; // NOT TO SPEC
// NOT TO SPEC:
// As we upgrade the receiver related entities from R5 to R7,
@@ -1904,15 +1943,15 @@
struct connect_t;
template <class _Tp>
-STDEXEC_R5_SENDER_DEPR_WARNING //
+STDEXEC_R5_SENDER_DEPRECATION_WARNING //
void
- __update_sender_type_to_p2300r7_by_adding_enable_sender_trait()
+ _PLEASE_UPDATE_YOUR_SENDER_TYPE()
{}
template <class _Tp>
-STDEXEC_R5_RECEIVER_DEPR_WARNING //
+STDEXEC_R5_RECEIVER_DEPRECATION_WARNING //
void
- __update_receiver_type_to_p2300r7_by_adding_enable_receiver_trait()
+ _PLEASE_UPDATE_YOUR_RECEIVER_TYPE()
{}
template <class _Sender, class _Receiver>
@@ -1929,12 +1968,10 @@
{
// Report that 2300R5-style senders and receivers are deprecated:
if constexpr (!enable_sender<__decay_t<_Sender>>)
- __update_sender_type_to_p2300r7_by_adding_enable_sender_trait<
- __decay_t<_Sender>>();
+ _PLEASE_UPDATE_YOUR_SENDER_TYPE<__decay_t<_Sender>>();
if constexpr (!enable_receiver<__decay_t<_Receiver>>)
- __update_receiver_type_to_p2300r7_by_adding_enable_receiver_trait<
- __decay_t<_Receiver>>();
+ _PLEASE_UPDATE_YOUR_RECEIVER_TYPE<__decay_t<_Receiver>>();
if constexpr (__connectable_with_tag_invoke<_Sender, _Receiver>)
{
@@ -2049,6 +2086,8 @@
template <class _Value>
struct __receiver_base
{
+ using is_receiver = void;
+
template <same_as<set_value_t> _Tag, class... _Us>
requires constructible_from<__value_or_void_t<_Value>, _Us...>
friend void tag_invoke(_Tag, __receiver_base&& __self,
@@ -2411,11 +2450,11 @@
template <class _ReceiverId>
struct __receiver
{
- using is_receiver = void;
using _Receiver = stdexec::__t<_ReceiverId>;
struct __t
{
+ using is_receiver = void;
using __id = __receiver;
__operation_base<_ReceiverId>* __op_state_;
@@ -2539,6 +2578,7 @@
struct __t
{
+ using is_receiver = void;
using __id = __detached_receiver;
STDEXEC_NO_UNIQUE_ADDRESS _Env __env_;
@@ -2759,6 +2799,7 @@
template <class _Fun>
struct __as_receiver
{
+ using is_receiver = void;
_Fun __fun_;
template <same_as<set_value_t> _Tag>
@@ -2931,7 +2972,7 @@
requires __decays_to<_Tp, _Tp>
{
static_assert(std::is_reference_v<__copy_cvref_t<_Up&&, _Tp>>);
- static_assert(std::is_base_of_v<_Tp, __decay_t<_Up>>);
+ static_assert(STDEXEC_IS_BASE_OF(_Tp, __decay_t<_Up>));
return (__copy_cvref_t<_Up&&, _Tp>)(_Up&&)u;
}
@@ -3032,7 +3073,7 @@
template <__class _Derived, class _Base>
struct receiver_adaptor
{
- class __t : __adaptor_base<_Base>
+ class __t : __adaptor_base<_Base>, __receiver_base
{
friend _Derived;
_DEFINE_MEMBER(set_value);
@@ -3269,6 +3310,7 @@
struct __t
{
+ using is_receiver = void;
using __id = __receiver;
__data* __op_;
@@ -3451,6 +3493,7 @@
struct __t
{
+ using is_receiver = void;
using __id = __receiver;
_Receiver __rcvr_;
@@ -3607,6 +3650,7 @@
struct __t
{
+ using is_receiver = void;
using __id = __receiver;
_Receiver __rcvr_;
STDEXEC_NO_UNIQUE_ADDRESS _Fun __fun_;
@@ -3955,6 +3999,7 @@
stdexec::__t<__sh_state<_CvrefSenderId, _EnvId>>& __sh_state_;
public:
+ using is_receiver = void;
using __id = __receiver;
template <__completion_tag _Tag, class... _As>
@@ -4311,6 +4356,7 @@
__shared_state_;
public:
+ using is_receiver = void;
using __id = __receiver;
explicit __t(stdexec::__t<__sh_state<_CvrefSenderId, _EnvId>>&
@@ -4769,6 +4815,7 @@
struct __t
{
+ using is_receiver = void;
using __id = __receiver_;
template <__one_of<_Set> _Tag, class... _As>
@@ -5465,6 +5512,7 @@
struct __t
{
+ using is_receiver = void;
using __id = __receiver2;
stdexec::__t<__operation1<_SchedulerId, _CvrefSenderId, _ReceiverId>>*
__op_state_;
@@ -5510,6 +5558,7 @@
struct __t
{
+ using is_receiver = void;
stdexec::__t<__operation1<_SchedulerId, _CvrefSenderId, _ReceiverId>>*
__op_state_;
@@ -6059,6 +6108,7 @@
struct __t
{
+ using is_receiver = void;
using __id = __receiver;
using _Receiver = stdexec::__t<_ReceiverId>;
_Receiver __rcvr_;
@@ -6378,6 +6428,7 @@
struct __t
{
+ using is_receiver = void;
using __id = __receiver;
template <class _Error>
@@ -6975,6 +7026,7 @@
{
struct __t
{
+ using is_receiver = void;
using __id = __receiver;
__state<_Values...>* __state_;
run_loop* __loop_;