Skip to content

Commit b84044a

Browse files
authored
Merge pull request #1896 from ericniebler/move-completion-behavior-to-exec
move `completion_behavior` utils to `::exec::`
2 parents 799d131 + b3af259 commit b84044a

18 files changed

Lines changed: 208 additions & 119 deletions
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
/*
2+
* Copyright (c) 2026 NVIDIA Corporation
3+
*
4+
* Licensed under the Apache License Version 2.0 with LLVM Exceptions
5+
* (the "License"); you may not use this file except in compliance with
6+
* the License. You may obtain a copy of the License at
7+
*
8+
* https://llvm.org/LICENSE.txt
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
#pragma once
17+
18+
#include "../stdexec/__detail/__execution_fwd.hpp"
19+
20+
// include these after __execution_fwd.hpp
21+
#include "../stdexec/__detail/__completion_behavior.hpp"
22+
23+
namespace experimental::execution
24+
{
25+
struct completion_behavior
26+
{
27+
using unknown_t = STDEXEC::__completion_behavior::__unknown_t;
28+
using asynchronous_t = STDEXEC::__completion_behavior::__asynchronous_t;
29+
using asynchronous_affine_t = STDEXEC::__completion_behavior::__asynchronous_affine_t;
30+
using inline_completion_t = STDEXEC::__completion_behavior::__inline_completion_t;
31+
using weakest_t = STDEXEC::__completion_behavior::__weakest_t;
32+
33+
static constexpr auto const &unknown = STDEXEC::__completion_behavior::__unknown;
34+
static constexpr auto const &asynchronous = STDEXEC::__completion_behavior::__asynchronous;
35+
static constexpr auto const &asynchronous_affine =
36+
STDEXEC::__completion_behavior::__asynchronous_affine;
37+
static constexpr auto const &inline_completion =
38+
STDEXEC::__completion_behavior::__inline_completion;
39+
static constexpr auto const &weakest = STDEXEC::__completion_behavior::__weakest;
40+
};
41+
42+
template <STDEXEC::__completion_tag _Tag>
43+
using get_completion_behavior_t = STDEXEC::__get_completion_behavior_t<_Tag>;
44+
45+
template <class _Tag, class _Sndr, class... _Env>
46+
STDEXEC_ATTRIBUTE(nodiscard, always_inline, host, device)
47+
constexpr auto get_completion_behavior() noexcept
48+
{
49+
return STDEXEC::__get_completion_behavior<_Tag, _Sndr, _Env...>();
50+
}
51+
} // namespace experimental::execution
52+
53+
namespace exec = experimental::execution;

include/exec/just_from.hpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717

1818
#include "../stdexec/__detail/__meta.hpp"
1919
#include "../stdexec/execution.hpp"
20+
#include "completion_behavior.hpp"
2021

2122
namespace experimental::execution
2223
{
@@ -128,9 +129,9 @@ namespace experimental::execution
128129
{
129130
template <STDEXEC::__one_of<Tags...> Tag>
130131
[[nodiscard]]
131-
constexpr auto query(STDEXEC::get_completion_behavior_t<Tag>) const noexcept
132+
constexpr auto query(get_completion_behavior_t<Tag>) const noexcept
132133
{
133-
return STDEXEC::completion_behavior::inline_completion;
134+
return completion_behavior::inline_completion;
134135
}
135136
};
136137

include/exec/task.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727

2828
#include "any_sender_of.hpp"
2929
#include "at_coroutine_exit.hpp"
30+
#include "completion_behavior.hpp"
3031
#include "scope.hpp"
3132

3233
STDEXEC_PRAGMA_PUSH()

include/exec/thread_pool_base.hpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -475,9 +475,9 @@ namespace experimental::execution
475475

476476
template <STDEXEC::__one_of<STDEXEC::set_value_t, STDEXEC::set_stopped_t> Tag>
477477
[[nodiscard]]
478-
constexpr auto query(STDEXEC::get_completion_behavior_t<Tag>) const noexcept
478+
constexpr auto query(STDEXEC::__get_completion_behavior_t<Tag>) const noexcept
479479
{
480-
return STDEXEC::completion_behavior::asynchronous;
480+
return STDEXEC::__completion_behavior::__asynchronous;
481481
}
482482

483483
[[nodiscard]]

include/stdexec/__detail/__affine_on.hpp

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -33,11 +33,11 @@ namespace STDEXEC
3333
{
3434
// For a given completion tag, a sender is "already affine" if either it doesn't send
3535
// that tag, or if its completion behavior for that tag is already "inline" or
36-
// "asynchronous_affine".
36+
// "__asynchronous_affine".
3737
template <class _Tag, class _Sender, class _Env>
3838
concept __already_affine = (!__sends<_Tag, _Sender, _Env>)
39-
|| (get_completion_behavior<_Tag, _Sender, _Env>()
40-
>= completion_behavior::asynchronous_affine);
39+
|| (__get_completion_behavior<_Tag, _Sender, _Env>()
40+
>= __completion_behavior::__asynchronous_affine);
4141

4242
// For the purpose of the affine_on algorithm, a sender that is "already affine" for
4343
// all three of the standard completion tags does not need to be adapted to become
@@ -119,11 +119,11 @@ namespace STDEXEC
119119
struct __attrs
120120
{
121121
template <class _Tag>
122-
constexpr auto query(get_completion_behavior_t<_Tag>) const noexcept
122+
constexpr auto query(__get_completion_behavior_t<_Tag>) const noexcept
123123
{
124124
// FUTURE: when the child sender completes inline *and* the current scheduler also
125-
// completes inline, we can return "inline" here instead of "asynchronous_affine".
126-
return completion_behavior::asynchronous_affine;
125+
// completes inline, we can return "inline" here instead of "__asynchronous_affine".
126+
return __completion_behavior::__asynchronous_affine;
127127
}
128128
};
129129
} // namespace __affine_on

include/stdexec/__detail/__completion_behavior.hpp

Lines changed: 96 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -29,123 +29,119 @@
2929
namespace STDEXEC
3030
{
3131
//////////////////////////////////////////////////////////////////////////////////////////
32-
// get_completion_behavior
33-
struct completion_behavior
32+
// __get_completion_behavior
33+
struct __completion_behavior
3434
{
35-
enum class behavior : int
35+
enum class __behavior : int
3636
{
37-
unknown, ///< The completion behavior is unknown.
38-
asynchronous, ///< The operation's completion will not always happen on the calling thread before `start()`
39-
///< returns.
40-
asynchronous_affine, ///< Like asynchronous, but completes where it starts.
41-
inline_completion ///< The operation completes synchronously within `start()` on the same thread that called
42-
///< `start()`.
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()`.
4343
};
4444

4545
STDEXEC_ATTRIBUTE(nodiscard, always_inline, host, device)
46-
friend constexpr auto operator<=>(behavior __a, behavior __b) noexcept -> std::strong_ordering
46+
friend constexpr auto
47+
operator<=>(__behavior __a, __behavior __b) noexcept -> std::strong_ordering
4748
{
4849
return static_cast<int>(__a) <=> static_cast<int>(__b);
4950
}
5051

5152
private:
52-
template <behavior _CB>
53-
using __constant_t = std::integral_constant<behavior, _CB>;
54-
55-
using __unknown_t = __constant_t<behavior::unknown>;
56-
using __asynchronous_t = __constant_t<behavior::asynchronous>;
57-
using __asynchronous_affine_t = __constant_t<behavior::asynchronous_affine>;
58-
using __inline_completion_t = __constant_t<behavior::inline_completion>;
53+
template <__behavior _CB>
54+
using __constant_t = std::integral_constant<__behavior, _CB>;
5955

6056
public:
61-
struct unknown_t : __unknown_t
62-
{};
63-
struct asynchronous_t : __asynchronous_t
64-
{};
65-
struct asynchronous_affine_t : __asynchronous_affine_t
66-
{};
67-
struct inline_completion_t : __inline_completion_t
68-
{};
69-
70-
static constexpr unknown_t unknown{};
71-
static constexpr asynchronous_t asynchronous{};
72-
static constexpr asynchronous_affine_t asynchronous_affine{};
73-
static constexpr inline_completion_t inline_completion{};
74-
75-
struct weakest_t
57+
struct __unknown_t : __constant_t<__behavior::__unknown>
58+
{ };
59+
struct __asynchronous_t : __constant_t<__behavior::__asynchronous>
60+
{ };
61+
struct __asynchronous_affine_t : __constant_t<__behavior::__asynchronous_affine>
62+
{ };
63+
struct __inline_completion_t : __constant_t<__behavior::__inline_completion>
64+
{ };
65+
66+
static constexpr __unknown_t __unknown{};
67+
static constexpr __asynchronous_t __asynchronous{};
68+
static constexpr __asynchronous_affine_t __asynchronous_affine{};
69+
static constexpr __inline_completion_t __inline_completion{};
70+
71+
struct __weakest_t
7672
{
77-
template <behavior... _CBs>
73+
template <__behavior... _CBs>
7874
STDEXEC_ATTRIBUTE(nodiscard, always_inline, host, device)
79-
constexpr auto operator()(completion_behavior::__constant_t<_CBs>...) const noexcept
75+
constexpr auto operator()(__completion_behavior::__constant_t<_CBs>...) const noexcept
8076
{
81-
constexpr auto __behavior = static_cast<behavior>(
77+
constexpr auto __behavior = static_cast<__completion_behavior::__behavior>(
8278
STDEXEC::__umin({static_cast<std::size_t>(_CBs)...}));
8379

84-
if constexpr (__behavior == completion_behavior::unknown)
80+
if constexpr (__behavior == __completion_behavior::__unknown)
8581
{
86-
return completion_behavior::unknown;
82+
return __completion_behavior::__unknown;
8783
}
88-
else if constexpr (__behavior == completion_behavior::asynchronous)
84+
else if constexpr (__behavior == __completion_behavior::__asynchronous)
8985
{
90-
return completion_behavior::asynchronous;
86+
return __completion_behavior::__asynchronous;
9187
}
92-
else if constexpr (__behavior == completion_behavior::asynchronous_affine)
88+
else if constexpr (__behavior == __completion_behavior::__asynchronous_affine)
9389
{
94-
return completion_behavior::asynchronous_affine;
90+
return __completion_behavior::__asynchronous_affine;
9591
}
96-
else if constexpr (__behavior == completion_behavior::inline_completion)
92+
else if constexpr (__behavior == __completion_behavior::__inline_completion)
9793
{
98-
return completion_behavior::inline_completion;
94+
return __completion_behavior::__inline_completion;
9995
}
10096
STDEXEC_UNREACHABLE();
10197
}
10298
};
10399

104-
static constexpr weakest_t weakest{};
100+
static constexpr __weakest_t __weakest{};
105101
};
106102

107103
//////////////////////////////////////////////////////////////////////////////////////////
108-
// get_completion_behavior: A sender can define this attribute to describe the sender's
104+
// __get_completion_behavior: A sender can define this attribute to describe the sender's
109105
// completion behavior
110106
template <__completion_tag _Tag>
111-
struct get_completion_behavior_t
107+
struct __get_completion_behavior_t
112108
{
113109
private:
114110
template <class _Attrs, class... _Env>
115111
STDEXEC_ATTRIBUTE(always_inline, host, device)
116112
static constexpr auto __validate() noexcept
117113
{
118-
using __result_t = __member_query_result_t<_Attrs, get_completion_behavior_t, _Env...>;
119-
static_assert(__nothrow_member_queryable_with<_Attrs, get_completion_behavior_t, _Env...>,
120-
"The get_completion_behavior query must be noexcept.");
121-
static_assert(__std::convertible_to<__result_t, completion_behavior::behavior>,
122-
"The get_completion_behavior query must return one of the static member "
114+
using __result_t = __member_query_result_t<_Attrs, __get_completion_behavior_t, _Env...>;
115+
static_assert(__nothrow_member_queryable_with<_Attrs, __get_completion_behavior_t, _Env...>,
116+
"The __get_completion_behavior query must be noexcept.");
117+
static_assert(__std::convertible_to<__result_t, __completion_behavior::__behavior>,
118+
"The __get_completion_behavior query must return one of the static member "
123119
"variables in "
124-
"execution::completion_behavior.");
120+
"execution::__completion_behavior.");
125121
return __result_t{};
126122
}
127123

128124
public:
129125
template <class _Sig>
130-
inline static constexpr get_completion_behavior_t (*signature)(_Sig) = nullptr;
126+
inline static constexpr __get_completion_behavior_t (*signature)(_Sig) = nullptr;
131127

132128
template <class _Attrs, class... _Env>
133129
STDEXEC_ATTRIBUTE(nodiscard, always_inline, host, device)
134130
constexpr auto operator()(_Attrs const &, _Env const &...) const noexcept
135131
{
136132
if constexpr (__member_queryable_with<_Attrs const &,
137-
get_completion_behavior_t<_Tag>,
133+
__get_completion_behavior_t<_Tag>,
138134
_Env...>)
139135
{
140136
return __validate<_Attrs, _Env...>();
141137
}
142-
else if constexpr (__member_queryable_with<_Attrs const &, get_completion_behavior_t<_Tag>>)
138+
else if constexpr (__member_queryable_with<_Attrs const &, __get_completion_behavior_t<_Tag>>)
143139
{
144140
return __validate<_Attrs>();
145141
}
146142
else
147143
{
148-
return completion_behavior::unknown;
144+
return __completion_behavior::__unknown;
149145
}
150146
}
151147

@@ -157,24 +153,61 @@ namespace STDEXEC
157153
};
158154

159155
template <class... _CBs>
160-
using __common_completion_behavior_t = __result_of<completion_behavior::weakest, _CBs...>;
156+
using __common_completion_behavior_t = __result_of<__completion_behavior::__weakest, _CBs...>;
161157

162158
template <class _Tag, class _Attrs, class... _Env>
163159
concept __completes_inline =
164-
(__call_result_t<get_completion_behavior_t<_Tag>, _Attrs const &, _Env const &...>{}
165-
== completion_behavior::inline_completion);
160+
(__call_result_t<__get_completion_behavior_t<_Tag>, _Attrs const &, _Env const &...>{}
161+
== __completion_behavior::__inline_completion);
166162

167163
template <class _Tag, class _Attrs, class... _Env>
168164
concept __completes_where_it_starts =
169-
(__call_result_t<get_completion_behavior_t<_Tag>, _Attrs const &, _Env const &...>{}
170-
>= completion_behavior::asynchronous_affine);
165+
(__call_result_t<__get_completion_behavior_t<_Tag>, _Attrs const &, _Env const &...>{}
166+
>= __completion_behavior::__asynchronous_affine);
171167

172168
template <class _Tag, class _Sndr, class... _Env>
173169
STDEXEC_ATTRIBUTE(nodiscard, always_inline, host, device)
174-
constexpr auto get_completion_behavior() noexcept
170+
constexpr auto __get_completion_behavior() noexcept
175171
{
176172
using __behavior_t =
177-
__call_result_t<get_completion_behavior_t<_Tag>, env_of_t<_Sndr>, _Env const &...>;
173+
__call_result_t<__get_completion_behavior_t<_Tag>, env_of_t<_Sndr>, _Env const &...>;
178174
return __behavior_t{};
179175
}
176+
177+
#if !defined(STDEXEC_DOXYGEN_INVOKED)
178+
179+
struct [[deprecated("Use exec::completion_behavior from "
180+
"<exec/completion_behavior.hpp> instead")]] completion_behavior
181+
{
182+
using unknown_t = __completion_behavior::__unknown_t;
183+
using asynchronous_t = __completion_behavior::__asynchronous_t;
184+
using asynchronous_affine_t = __completion_behavior::__asynchronous_affine_t;
185+
using inline_completion_t = __completion_behavior::__inline_completion_t;
186+
using weakest_t = __completion_behavior::__weakest_t;
187+
188+
static constexpr auto const &unknown = __completion_behavior::__unknown;
189+
static constexpr auto const &asynchronous = __completion_behavior::__asynchronous;
190+
static constexpr auto const &asynchronous_affine = __completion_behavior::__asynchronous_affine;
191+
static constexpr auto const &inline_completion = __completion_behavior::__inline_completion;
192+
static constexpr auto const &weakest = __completion_behavior::__weakest;
193+
};
194+
195+
template <__completion_tag _Tag>
196+
using get_completion_behavior_t [[deprecated("Use exec::get_completion_behavior from "
197+
"<exec/completion_behavior.hpp> instead")]]
198+
= __get_completion_behavior_t<_Tag>;
199+
200+
// clang-format off
201+
template <class _Tag, class _Sndr, class... _Env>
202+
[[deprecated("Use exec::get_completion_behavior from <exec/completion_behavior.hpp> "
203+
"instead")]]
204+
STDEXEC_ATTRIBUTE(nodiscard, always_inline, host, device)
205+
constexpr auto get_completion_behavior() noexcept
206+
{
207+
return __get_completion_behavior<_Tag, _Sndr, _Env...>();
208+
}
209+
// clang-format on
210+
211+
#endif // !defined(STDEXEC_DOXYGEN_INVOKED)
212+
180213
} // namespace STDEXEC

include/stdexec/__detail/__continues_on.hpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -284,14 +284,14 @@ namespace STDEXEC
284284
//! the original sender.
285285
template <class _Tag, class... _Env>
286286
[[nodiscard]]
287-
constexpr auto query(get_completion_behavior_t<_Tag>, _Env const &...) const noexcept
287+
constexpr auto query(__get_completion_behavior_t<_Tag>, _Env const &...) const noexcept
288288
{
289289
using _SchSender = schedule_result_t<_Scheduler>;
290290
constexpr auto cb_sched =
291-
STDEXEC::get_completion_behavior<_Tag, _SchSender, __fwd_env_t<_Env>...>();
291+
STDEXEC::__get_completion_behavior<_Tag, _SchSender, __fwd_env_t<_Env>...>();
292292
constexpr auto cb_sndr =
293-
STDEXEC::get_completion_behavior<_Tag, _Sender, __fwd_env_t<_Env>...>();
294-
return completion_behavior::weakest(cb_sched, cb_sndr);
293+
STDEXEC::__get_completion_behavior<_Tag, _Sender, __fwd_env_t<_Env>...>();
294+
return __completion_behavior::__weakest(cb_sched, cb_sndr);
295295
}
296296

297297
//! @brief Forwards other queries to the underlying sender's environment.

include/stdexec/__detail/__deprecations.hpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,8 @@ namespace STDEXEC
2525
inline constexpr __execute_may_block_caller_t const & execute_may_block_caller =
2626
__execute_may_block_caller;
2727

28-
[[deprecated("use STDEXEC::completion_behavior::weakest instead")]]
29-
inline constexpr auto const & min = completion_behavior::weakest;
28+
[[deprecated("use STDEXEC::__completion_behavior::__weakest instead")]]
29+
inline constexpr auto const & min = __completion_behavior::__weakest;
3030

3131
using empty_env [[deprecated("STDEXEC::empty_env is now spelled STDEXEC::env<>")]] = env<>;
3232

0 commit comments

Comments
 (0)