Skip to content

Commit c03da7a

Browse files
stdexec::stoppable_token & ::stop_token_for_t: Support std::stop_token (#1726)
Both the stdexec::stoppable_token concept and the stdexec:: stop_token_for_t template type alias depend on the stop token type having a unary member template named callback_type. While P2300 added the aforementioned member template to std::stop_token that means that before C++26 the aforementioned utilities don't work therewith. Special cased: - stdexec::stoppable_token to allow std::stop_token without checking for the above-mentioned member template, and - stdexec::stop_token_t to resolve to std::stop_callback<Callback> when its first template argument is std::stop_token --------- Co-authored-by: Eric Niebler <[email protected]>
1 parent 4b90a66 commit c03da7a

File tree

3 files changed

+74
-4
lines changed

3 files changed

+74
-4
lines changed

include/stdexec/__detail/__stop_token.hpp

Lines changed: 31 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,26 +20,53 @@
2020

2121
#include "__concepts.hpp"
2222

23+
STDEXEC_NAMESPACE_STD_BEGIN
24+
class stop_token;
25+
26+
template <class _Callback>
27+
class stop_callback;
28+
STDEXEC_NAMESPACE_STD_END
29+
2330
namespace stdexec {
2431
namespace __stok {
2532
template <template <class> class>
2633
struct __check_type_alias_exists;
2734
} // namespace __stok
2835

2936
template <class _Token, class _Callback>
30-
using stop_callback_for_t = _Token::template callback_type<_Callback>;
37+
struct __stop_callback_for {
38+
using __t = _Token::template callback_type<_Callback>;
39+
};
40+
template <class _Callback>
41+
struct __stop_callback_for<std::stop_token, _Callback> {
42+
using __t = std::stop_callback<_Callback>;
43+
};
44+
45+
template <class _Token, class _Callback>
46+
using stop_callback_for_t = __stop_callback_for<_Token, _Callback>::__t;
3147

3248
template <class _Token>
33-
concept stoppable_token =
49+
concept __stoppable_token =
3450
__nothrow_copy_constructible<_Token> && __nothrow_move_constructible<_Token>
3551
&& equality_comparable<_Token> && requires(const _Token& __token) {
3652
{ __token.stop_requested() } noexcept -> __boolean_testable_;
3753
{ __token.stop_possible() } noexcept -> __boolean_testable_;
38-
// workaround ICE in appleclang 13.1
54+
}
55+
// workaround ICE in appleclang 13.1
3956
#if !defined(__clang__)
57+
&& requires {
4058
typename __stok::__check_type_alias_exists<_Token::template callback_type>;
59+
}
4160
#endif
42-
};
61+
;
62+
63+
template <class _Token>
64+
concept __stoppable_token_or = __same_as<_Token, std::stop_token> || __stoppable_token<_Token>;
65+
66+
// The cast to bool below is to make __stoppable_token_or<_Token> an atomic constraint,
67+
// hiding the disjunction within it for the sake of better compile-time performance.
68+
template <class _Token>
69+
concept stoppable_token = bool(__stoppable_token_or<_Token>);
4370

4471
template <class _Token, typename _Callback, typename _Initializer = _Callback>
4572
concept stoppable_token_for =

test/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ set(stdexec_test_sources
2929
stdexec/concepts/test_concepts_receiver.cpp
3030
stdexec/concepts/test_concept_operation_state.cpp
3131
stdexec/concepts/test_concepts_sender.cpp
32+
stdexec/concepts/test_concepts_stop_tokens.cpp
3233
stdexec/concepts/test_awaitables.cpp
3334
stdexec/algos/factories/test_just.cpp
3435
stdexec/algos/factories/test_transfer_just.cpp
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
/*
2+
* SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
3+
* Copyright (c) 2025 Robert Leahy. All rights reserved.
4+
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
5+
*
6+
* Licensed under the Apache License, Version 2.0 with LLVM Exceptions (the "License");
7+
* you may not use this file except in compliance with the License.
8+
* You may obtain a copy of the License at
9+
*
10+
* https://llvm.org/LICENSE.txt
11+
*
12+
* Unless required by applicable law or agreed to in writing, software
13+
* distributed under the License is distributed on an "AS IS" BASIS,
14+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
* See the License for the specific language governing permissions and
16+
* limitations under the License.
17+
*/
18+
19+
#include <stdexec/execution.hpp>
20+
21+
#include <type_traits>
22+
23+
namespace {
24+
25+
struct on_stop_request {
26+
void operator()() && noexcept {
27+
}
28+
};
29+
30+
static_assert(::stdexec::stoppable_token<::stdexec::never_stop_token>);
31+
static_assert(::stdexec::unstoppable_token<::stdexec::never_stop_token>);
32+
static_assert(::stdexec::stoppable_token<::stdexec::inplace_stop_token>);
33+
static_assert(!::stdexec::unstoppable_token<::stdexec::inplace_stop_token>);
34+
static_assert(std::is_same_v<
35+
::stdexec::stop_callback_for_t<::stdexec::never_stop_token, on_stop_request>,
36+
::stdexec::never_stop_token::callback_type<on_stop_request>>);
37+
static_assert(::stdexec::stoppable_token<std::stop_token>);
38+
static_assert(std::is_same_v<
39+
::stdexec::stop_callback_for_t<std::stop_token, on_stop_request>,
40+
std::stop_callback<on_stop_request>>);
41+
42+
} // namespace

0 commit comments

Comments
 (0)