Skip to content

Commit 054624f

Browse files
authored
Merge pull request NVIDIA#1890 from ericniebler/allocator-aware-forward
implement _`allocator-aware-forward`_ from [exec.snd.expos]
2 parents 3e2ac88 + f0a941e commit 054624f

6 files changed

Lines changed: 72 additions & 16 deletions

File tree

include/stdexec/__detail/__associate.hpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -185,7 +185,7 @@ namespace STDEXEC
185185
};
186186

187187
explicit __op_state(std::pair<__assoc_t, __sender_ref_t> __parts, _Receiver&& __rcvr)
188-
: __assoc_(std::move(__parts.first))
188+
: __assoc_(STDEXEC::__allocator_aware_forward(std::move(__parts.first), __rcvr))
189189
{
190190
if (__assoc_)
191191
{
@@ -264,7 +264,7 @@ namespace STDEXEC
264264
auto& [__tag, __data] = __self;
265265

266266
using op_state_t = __op_state<std::remove_cvref_t<_Self>, _Receiver>;
267-
return op_state_t{__forward_like<_Self>(__data), std::move(__rcvr)};
267+
return op_state_t{STDEXEC::__forward_like<_Self>(__data), std::move(__rcvr)};
268268
};
269269

270270
static constexpr auto __start = [](auto& __state) noexcept -> void

include/stdexec/__detail/__basic_sender.hpp

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#include "__connect.hpp"
2323
#include "__diagnostics.hpp"
2424
#include "__env.hpp"
25+
#include "__memory.hpp"
2526
#include "__meta.hpp"
2627
#include "__operation_states.hpp"
2728
#include "__receivers.hpp"
@@ -104,6 +105,14 @@ namespace STDEXEC
104105
using __receiver_t = _Receiver;
105106
using __data_t = _Data;
106107

108+
template <class _CvData>
109+
STDEXEC_ATTRIBUTE(host, device)
110+
constexpr __state(_Receiver __rcvr, _CvData&& __data)
111+
noexcept(__nothrow_decay_copyable<_CvData>)
112+
: __rcvr_(static_cast<_Receiver&&>(__rcvr))
113+
, __data_(STDEXEC::__allocator_aware_forward(static_cast<_CvData&&>(__data), __rcvr_))
114+
{ }
115+
107116
STDEXEC_IMMOVABLE_NO_UNIQUE_ADDRESS
108117
_Receiver __rcvr_;
109118
STDEXEC_IMMOVABLE_NO_UNIQUE_ADDRESS
@@ -160,17 +169,17 @@ namespace STDEXEC
160169
STDEXEC::__get<1>(static_cast<_Sender&&>(__sndr))};
161170
};
162171

163-
static constexpr auto __get_env = //
164-
[]<class _State>(__ignore,
165-
_State const & __state) noexcept -> env_of_t<decltype(_State::__rcvr_)>
172+
static constexpr auto __get_env = //
173+
[]<class _State>(__ignore, _State const & __state) noexcept //
174+
-> env_of_t<decltype(_State::__rcvr_)>
166175
{
167176
return STDEXEC::get_env(__state.__rcvr_);
168177
};
169178

170179
static constexpr auto __connect = //
171180
[]<class _Receiver, __connectable_to<_Receiver> _Sender>(_Sender&& __sndr,
172-
_Receiver&& __rcvr) //
173-
noexcept(__nothrow_constructible_from<__opstate<_Sender, _Receiver>, _Sender, _Receiver>)
181+
_Receiver&& __rcvr) noexcept( //
182+
__nothrow_constructible_from<__opstate<_Sender, _Receiver>, _Sender, _Receiver>)
174183
-> __opstate<_Sender, _Receiver>
175184
{
176185
return __opstate<_Sender, _Receiver>(static_cast<_Sender&&>(__sndr),

include/stdexec/__detail/__let.hpp

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -295,7 +295,7 @@ namespace STDEXEC
295295
_Fun __fn,
296296
_Receiver&& __rcvr) noexcept
297297
: __rcvr_(static_cast<_Receiver&&>(__rcvr))
298-
, __fn_(static_cast<_Fun&&>(__fn))
298+
, __fn_(STDEXEC::__allocator_aware_forward(static_cast<_Fun&&>(__fn), __rcvr_))
299299
// TODO(ericniebler): this needs a fallback:
300300
, __env2_(__let::__mk_env2<_SetTag>(__attrs, STDEXEC::get_env(__rcvr_)))
301301
{}
@@ -641,7 +641,7 @@ namespace STDEXEC
641641
//! Implementation of the `let_*_t` types, where `_SetTag` is, e.g., `set_value_t` for `let_value`.
642642
template <class _LetTag>
643643
struct __let_t
644-
{ // NOLINT(bugprone-crtp-constructor-accessibility)
644+
{
645645
using __t = decltype(__set_tag_from_let_v<_LetTag>());
646646

647647
template <sender _Sender, __movable_value _Fun>
@@ -656,6 +656,10 @@ namespace STDEXEC
656656
{
657657
return __closure(*this, static_cast<_Fun&&>(__fn));
658658
}
659+
660+
private:
661+
friend _LetTag;
662+
__let_t() = default;
659663
};
660664

661665
template <class _LetTag>
@@ -722,11 +726,17 @@ namespace STDEXEC
722726
} // namespace __let
723727

724728
struct let_value_t : __let::__let_t<let_value_t>
725-
{};
729+
{
730+
let_value_t() = default;
731+
};
726732
struct let_error_t : __let::__let_t<let_error_t>
727-
{};
733+
{
734+
let_error_t() = default;
735+
};
728736
struct let_stopped_t : __let::__let_t<let_stopped_t>
729-
{};
737+
{
738+
let_stopped_t() = default;
739+
};
730740

731741
inline constexpr let_value_t let_value{};
732742
inline constexpr let_error_t let_error{};

include/stdexec/__detail/__memory.hpp

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

1818
#include "__execution_fwd.hpp"
1919
#include "__scope.hpp"
20+
#include "__tuple.hpp"
2021

2122
// include these after __execution_fwd.hpp
2223
#include <memory> // IWYU pragma: export
@@ -87,4 +88,39 @@ namespace STDEXEC
8788
requires __same_as<_Ty, typename _Alloc::value_type>
8889
[[nodiscard]]
8990
constexpr auto __rebind_allocator(_Alloc const &&) noexcept = delete;
91+
92+
/////////////////////////////////////////////////////////////////////////////////////////
93+
// __allocator_aware_forward: https://eel.is/c++draft/exec#snd.expos-49
94+
template <class _Alloc>
95+
[[nodiscard]]
96+
constexpr auto __mk_obj_using_alloc_fn(_Alloc const &__alloc) noexcept
97+
{
98+
return [&__alloc]<class... _Args>(_Args &&...__args)
99+
{
100+
return __tuple{
101+
std::make_obj_using_allocator<__decay_t<_Args>>(__alloc, static_cast<_Args &&>(__args))...};
102+
};
103+
}
104+
105+
template <class _Ty, class _Context>
106+
[[nodiscard]]
107+
constexpr auto __allocator_aware_forward(_Ty &&__obj, _Context const &__ctx) -> decltype(auto)
108+
{
109+
using __value_t = __decay_t<_Ty>;
110+
if constexpr (!__callable<get_allocator_t, env_of_t<_Context>>)
111+
{
112+
return static_cast<_Ty &&>(__obj);
113+
}
114+
else if constexpr (__is_instance_of<__value_t, __tuple>)
115+
{
116+
auto const __alloc = get_allocator(get_env(__ctx));
117+
return __apply(STDEXEC::__mk_obj_using_alloc_fn(__alloc), static_cast<_Ty &&>(__obj));
118+
}
119+
else
120+
{
121+
auto const __alloc = get_allocator(get_env(__ctx));
122+
return std::make_obj_using_allocator<__decay_t<_Ty>>(__alloc, static_cast<_Ty &&>(__obj));
123+
}
124+
}
125+
90126
} // namespace STDEXEC

include/stdexec/__detail/__stop_when.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -184,7 +184,7 @@ namespace STDEXEC
184184
[]<class _Self, class _Receiver>(_Self&& __self, _Receiver __rcvr) noexcept
185185
{
186186
auto& [__tag, __token, __child] = __self;
187-
auto __new_token = __make_token_fn{}(__forward_like<_Self>(__token),
187+
auto __new_token = __make_token_fn{}(STDEXEC::__forward_like<_Self>(__token),
188188
get_stop_token(STDEXEC::get_env(__rcvr)));
189189
return __state{std::move(__new_token), std::move(__rcvr)};
190190
};

include/stdexec/__detail/__utility.hpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -197,10 +197,11 @@ namespace STDEXEC
197197
}
198198

199199
template <class _Ty>
200-
constexpr _Ty const & __clamp(_Ty const & v, _Ty const & lo, _Ty const & hi)
200+
constexpr _Ty const & __clamp(_Ty const & __val, _Ty const & __low, _Ty const & __high)
201201
{
202-
STDEXEC_ASSERT(!(hi < lo));
203-
return v < lo ? lo : hi < v ? hi : v; // NOLINT(bugprone-return-const-ref-from-parameter)
202+
STDEXEC_ASSERT(!(__high < __low));
203+
// NOLINTNEXTLINE(bugprone-return-const-ref-from-parameter)
204+
return __val < __low ? __low : __high < __val ? __high : __val;
204205
}
205206

206207
STDEXEC_PRAGMA_PUSH()

0 commit comments

Comments
 (0)