2323#include " __query.hpp"
2424#include " __utility.hpp"
2525
26- #include < compare >
26+ #include < cstdint >
2727#include < type_traits>
2828
2929namespace STDEXEC
@@ -32,24 +32,35 @@ namespace STDEXEC
3232 // __get_completion_behavior
3333 struct __completion_behavior
3434 {
35- enum class __behavior : int
35+ // private:
36+ template <__completion_tag _Tag>
37+ friend struct __get_completion_behavior_t ;
38+
39+ enum __flag : std::uint8_t
3640 {
37- __unknown, // /< The completion behavior is unknown.
38- __asynchronous, // /< The operation's completion will not always happen on
39- // /< the calling thread before `start()` returns.
40- __asynchronous_affine, // /< Like asynchronous, but completes where it starts.
41- __inline_completion // /< The operation completes synchronously within `start()`
42- // /< on the same thread that called `start()`.
41+ __not_affine_ = 1 ,
42+ __async_ = 2 ,
43+ __inline_ = 4
4344 };
4445
45- STDEXEC_ATTRIBUTE (nodiscard, always_inline, host, device)
46- friend constexpr auto
47- operator <=>(__behavior __a, __behavior __b) noexcept -> std::strong_ordering
46+ enum class __behavior : std::uint8_t
4847 {
49- return static_cast <int >(__a) <=> static_cast <int >(__b);
50- }
48+ // The operation will complete asynchronously, and may complete on a different
49+ // context than the one that started it.
50+ __asynchronous = __async_ | __not_affine_,
51+
52+ // The operation will complete asynchronously, but will complete on the same
53+ // context that started it.
54+ __asynchronous_affine = __async_,
55+
56+ // The operation will complete synchronously (before 'start()' returns) on the same
57+ // thread that started it.
58+ __inline_completion = __inline_,
59+
60+ // The operation's completion behavior is unknown.
61+ __unknown = __not_affine_ | __async_ | __inline_
62+ };
5163
52- private:
5364 template <__behavior _CB>
5465 using __constant_t = std::integral_constant<__behavior, _CB>;
5566
@@ -68,36 +79,57 @@ namespace STDEXEC
6879 static constexpr __asynchronous_affine_t __asynchronous_affine{};
6980 static constexpr __inline_completion_t __inline_completion{};
7081
71- struct __weakest_t
82+ // __asynchronous | __asynchronous_affine => __async_ (aka __asynchronous)
83+ // __asynchronous | __inline_completion => __async_ | __inline_ | __not_affine (aka __unknown)
84+ // __asynchronous_affine | __inline_completion => __async_ | __inline_
85+ template <__behavior _Left, __behavior _Right>
86+ STDEXEC_ATTRIBUTE (nodiscard, always_inline, host, device)
87+ friend constexpr auto operator |(__constant_t <_Left>, __constant_t <_Right>) noexcept
88+ {
89+ return __constant_t <static_cast <__behavior>(static_cast <std::uint8_t >(_Left)
90+ | static_cast <std::uint8_t >(_Right))>();
91+ }
92+
93+ template <__behavior _Left, __behavior _Right>
94+ STDEXEC_ATTRIBUTE (nodiscard, always_inline, host, device)
95+ friend constexpr bool operator ==(__constant_t <_Left>, __constant_t <_Right>) noexcept
96+ {
97+ return _Left == _Right;
98+ }
99+
100+ template <__behavior _CB>
101+ STDEXEC_ATTRIBUTE (nodiscard, always_inline, host, device)
102+ static constexpr bool __is_affine (__constant_t <_CB>) noexcept
103+ {
104+ return !(static_cast <std::uint8_t >(_CB) & __not_affine_);
105+ }
106+
107+ template <__behavior _CB>
108+ STDEXEC_ATTRIBUTE (nodiscard, always_inline, host, device)
109+ static constexpr bool __is_always_asynchronous (__constant_t <_CB>) noexcept
110+ {
111+ return !(static_cast <std::uint8_t >(_CB) & __inline_);
112+ }
113+
114+ template <__behavior _CB>
115+ STDEXEC_ATTRIBUTE (nodiscard, always_inline, host, device)
116+ static constexpr bool __may_be_asynchronous (__constant_t <_CB>) noexcept
72117 {
73- template <__behavior... _CBs>
74- STDEXEC_ATTRIBUTE (nodiscard, always_inline, host, device)
75- constexpr auto operator ()(__completion_behavior::__constant_t <_CBs>...) const noexcept
118+ return bool (static_cast <std::uint8_t >(_CB) & __async_);
119+ }
120+
121+ struct __common_t
122+ {
123+ template <__behavior... _CSs>
124+ requires (sizeof ...(_CSs) > 0 )
125+ STDEXEC_ATTRIBUTE (nodiscard, host, device)
126+ constexpr auto operator ()(__constant_t <_CSs>... __cbs) const noexcept
76127 {
77- constexpr auto __behavior = static_cast <__completion_behavior::__behavior>(
78- STDEXEC::__umin ({static_cast <std::size_t >(_CBs)...}));
79-
80- if constexpr (__behavior == __completion_behavior::__unknown)
81- {
82- return __completion_behavior::__unknown;
83- }
84- else if constexpr (__behavior == __completion_behavior::__asynchronous)
85- {
86- return __completion_behavior::__asynchronous;
87- }
88- else if constexpr (__behavior == __completion_behavior::__asynchronous_affine)
89- {
90- return __completion_behavior::__asynchronous_affine;
91- }
92- else if constexpr (__behavior == __completion_behavior::__inline_completion)
93- {
94- return __completion_behavior::__inline_completion;
95- }
96- STDEXEC_UNREACHABLE ();
128+ return (__cbs | ...);
97129 }
98130 };
99131
100- static constexpr __weakest_t __weakest {};
132+ static constexpr __common_t __common {};
101133 };
102134
103135 // ////////////////////////////////////////////////////////////////////////////////////////
@@ -116,8 +148,7 @@ namespace STDEXEC
116148 " The __get_completion_behavior query must be noexcept." );
117149 static_assert (__std::convertible_to<__result_t , __completion_behavior::__behavior>,
118150 " The __get_completion_behavior query must return one of the static member "
119- " variables in "
120- " execution::__completion_behavior." );
151+ " variables in STDEXEC::__completion_behavior." );
121152 return __result_t {};
122153 }
123154
@@ -152,26 +183,23 @@ namespace STDEXEC
152183 }
153184 };
154185
155- template <class ... _CBs>
156- using __common_completion_behavior_t = __result_of<__completion_behavior::__weakest, _CBs...>;
186+ template <class _Tag , class _Attrs , class ... _Env>
187+ inline constexpr auto __completion_behavior_of_v =
188+ __call_result_t <__get_completion_behavior_t <_Tag>, _Attrs const &, _Env const &...>{};
157189
158190 template <class _Tag , class _Attrs , class ... _Env>
159- concept __completes_inline =
160- (__call_result_t <__get_completion_behavior_t <_Tag>, _Attrs const &, _Env const &...>{}
161- == __completion_behavior::__inline_completion);
191+ concept __completes_inline = (__completion_behavior_of_v<_Tag, _Attrs, _Env...>
192+ == __completion_behavior::__inline_completion);
162193
163194 template <class _Tag , class _Attrs , class ... _Env>
164- concept __completes_where_it_starts =
165- (__call_result_t <__get_completion_behavior_t <_Tag>, _Attrs const &, _Env const &...>{}
166- >= __completion_behavior::__asynchronous_affine);
195+ concept __completes_where_it_starts = __completion_behavior::__is_affine(
196+ __completion_behavior_of_v<_Tag, _Attrs, _Env...>);
167197
168198 template <class _Tag , class _Sndr , class ... _Env>
169199 STDEXEC_ATTRIBUTE (nodiscard, always_inline, host, device)
170200 constexpr auto __get_completion_behavior() noexcept
171201 {
172- using __behavior_t =
173- __call_result_t <__get_completion_behavior_t <_Tag>, env_of_t <_Sndr>, _Env const &...>;
174- return __behavior_t {};
202+ return __completion_behavior_of_v<_Tag, env_of_t <_Sndr>, _Env...>;
175203 }
176204
177205#if !defined(STDEXEC_DOXYGEN_INVOKED)
@@ -183,13 +211,11 @@ namespace STDEXEC
183211 using asynchronous_t = __completion_behavior::__asynchronous_t ;
184212 using asynchronous_affine_t = __completion_behavior::__asynchronous_affine_t ;
185213 using inline_completion_t = __completion_behavior::__inline_completion_t ;
186- using weakest_t = __completion_behavior::__weakest_t ;
187214
188215 static constexpr auto const &unknown = __completion_behavior::__unknown;
189216 static constexpr auto const &asynchronous = __completion_behavior::__asynchronous;
190217 static constexpr auto const &asynchronous_affine = __completion_behavior::__asynchronous_affine;
191218 static constexpr auto const &inline_completion = __completion_behavior::__inline_completion;
192- static constexpr auto const &weakest = __completion_behavior::__weakest;
193219 };
194220
195221 template <__completion_tag _Tag>
0 commit comments