Unifex uses a generic stop_token_concept to support the cancellation of asynchronous operations. A stop-token is passed to an operation to allow a request for that operation to stop executing (e.g., when its result is no longer needed).
Unlike standard C++20 std::stop_token, Unifex uses a concept-based approach to allow for more efficient implementations, such as avoiding heap allocation or reference counting in structured concurrency scenarios.
Key requirements for a type to satisfy stop_token_concept:
- Must be
std::copyable and support no-throw copy/move construction. - Must provide a nested template type alias:
typename T::template callback_type<CallbackArchetype>. - Must provide
stop_requested() and stop_possible() methods that are noexcept. - The
callback_type must be destructible and support no-throw construction from the token and a callback archetype.
Note on std::stop_token compatibility:
Currently, std::stop_token does not satisfy the Unifex stop_token_concept because it lacks the required nested callback_type template type alias.
namespace unifex
{
struct __stop_token_callback_archetype {
// These have no definitions.
__stop_token_callback_archetype() noexcept;
__stop_token_callback_archetype(__stop_token_callback_archetype&&) noexcept;
__stop_token_callback_archetype(const __stop_token_callback_archetype&) noexcept;
~__stop_token_callback_archetype();
void operator()() noexcept;
};
template<typename T>
concept stop_token_concept =
std::copyable<T> &&
std::is_nothrow_copy_constructible_v<T> &&
std::is_nothrow_move_constructible_v<T> &&
requires(const T token) {
typename T::template callback_type<__stop_token_callback_archetype>;
{ token.stop_requested() ? (void)0 : (void)0 } noexcept;
{ token.stop_possible() ? (void)0 : (void)0 } noexcept;
} &&
std::destructible<
typename T::template callback_type<__stop_token_callback_archetype>> &&
std::is_nothrow_constructible_v(
typename T::template callback_type<__stop_token_callback_archetype>,
T, __stop_token_callback_archetype) &&
std::is_nothrow_constructible_v(
typename T::template callback_type<__stop_token_callback_archetype>,
const T&, __stop_token_callback_archetype);
}