Skip to content

Commit 5625b5e

Browse files
Fix nvexec split pre-cancellation (#2186)
* Fix nvexec split pre-cancellation * fix nvexec split pre-cancellation test --------- Co-authored-by: Eric Niebler <eniebler@nvidia.com>
1 parent 92dc830 commit 5625b5e

2 files changed

Lines changed: 42 additions & 3 deletions

File tree

include/nvexec/stream/split.cuh

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,11 @@ namespace nv::execution::_strm
150150
template <class Sender>
151151
struct sh_state
152152
{
153-
using variant_t = variant_storage_t<Sender, env_t>;
153+
using variant_t = __for_each_completion_signature_t<
154+
__concat_completion_signatures_t<__completion_signatures_of_t<Sender, env_t>,
155+
completion_signatures<set_stopped_t()>>,
156+
decayed_tuple_t,
157+
__munique<__q<_nullable_variant_t>>::__f>;
154158
using inner_receiver_t = receiver<Sender, sh_state>;
155159
using task_t = continuation_task<inner_receiver_t, variant_t>;
156160
using enqueue_receiver_t = stream_enqueue_receiver<env_t, variant_t>;
@@ -165,6 +169,7 @@ namespace nv::execution::_strm
165169
, data_(malloc_managed<variant_t>(stream_provider_.status_))
166170
, opstate2_(connect(static_cast<Sender&&>(sndr), inner_receiver_t{*this}))
167171
{
172+
_initialize_stopped();
168173
if (stream_provider_.status_ == cudaSuccess)
169174
{
170175
stream_provider_.status_ = STDEXEC_LOG_CUDA_API(
@@ -186,7 +191,9 @@ namespace nv::execution::_strm
186191
, env_(host_allocate(this->stream_provider_.status_, ctx_.pinned_resource_, make_env()))
187192
, opstate2_(connect(static_cast<Sender&&>(sndr),
188193
enqueue_receiver_t{env_.get(), data_, task_, ctx.hub_->producer()}))
189-
{}
194+
{
195+
_initialize_stopped();
196+
}
190197

191198
~sh_state()
192199
{
@@ -213,6 +220,16 @@ namespace nv::execution::_strm
213220
return _split::_make_env(stop_source_, &const_cast<stream_provider&>(stream_provider_));
214221
}
215222

223+
void _initialize_stopped() noexcept
224+
{
225+
if (data_)
226+
{
227+
using tuple_t = decayed_tuple_t<set_stopped_t>;
228+
index_ = __mapply<__mfind_i<tuple_t>, variant_t>::value;
229+
data_->template emplace<tuple_t>(set_stopped_t());
230+
}
231+
}
232+
216233
void notify() noexcept
217234
{
218235
void* const completion_state = static_cast<void*>(this);
@@ -359,7 +376,7 @@ namespace nv::execution::_strm
359376
return STDEXEC::__transform_completion_signatures_of_t<
360377
Sender,
361378
STDEXEC::prop<get_stop_token_t, inplace_stop_token>,
362-
STDEXEC::completion_signatures<set_error_t(cudaError_t const &)>,
379+
STDEXEC::completion_signatures<set_error_t(cudaError_t const &), set_stopped_t()>,
363380
_set_value_t,
364381
_set_error_t>();
365382
}

test/nvexec/split.cpp

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,28 @@ namespace
3636
REQUIRE(v2 == 42);
3737
}
3838

39+
TEST_CASE("nvexec split handles pre-cancellation", "[cuda][stream][adaptors][split]")
40+
{
41+
nvexec::stream_context stream_ctx{};
42+
ex::inplace_stop_source stop_source;
43+
flags_storage_t flags_storage{};
44+
auto flags = flags_storage.get();
45+
46+
stop_source.request_stop();
47+
48+
auto snd = ex::schedule(stream_ctx.get_scheduler()) //
49+
| ex::then([flags] { flags.set(); }) //
50+
| exec::split() //
51+
| ex::write_env(ex::prop{ex::get_stop_token, stop_source.get_token()}) //
52+
| ex::then([] { return 0; }) //
53+
| ex::upon_stopped([] { return 42; });
54+
55+
auto [value] = STDEXEC::sync_wait(std::move(snd)).value();
56+
57+
REQUIRE(value == 42);
58+
REQUIRE(flags_storage.all_unset());
59+
}
60+
3961
TEST_CASE("nvexec split can preceed a sender without values", "[cuda][stream][adaptors][split]")
4062
{
4163
nvexec::stream_context stream_ctx{};

0 commit comments

Comments
 (0)