namespace std {
template<class Token>
concept stoppable_token;
}
概要
stoppable_token
は、型Token
が停止トークンとしての基本的なインタフェースを提供することを表すコンセプトである。
要件
まず、説明専用クラステンプレートcheck-type-alias-exists
を以下のように定義する。
template<template<class> class>
struct check-type-alias-exists;
stoppable_token
コンセプトは、以下のように定義される。
template<class Token>
concept stoppable_token =
requires (const Token tok) {
typename check-type-alias-exists<Token::template callback_type>;
{ tok.stop_requested() } noexcept -> same_as<bool>;
{ tok.stop_possible() } noexcept -> same_as<bool>;
{ Token(tok) } noexcept;
} &&
copyable<Token> &&
equality_comparable<Token> &&
swappable<Token>;
モデル
説明用の変数t
, u
を、同一の停止状態を参照する別々なToken
型オブジェクトとする。
型Token
が以下を満たす場合に限って、型Token
はstoppable_token
のモデルである。
SP
をt.stop_possible()
がfalse
となる評価としたとき、SP
より後に発生するu.stop_possible()
やu.stop_requested()
の評価はfalse
であること。SR
をt.stop_requested()
がtrue
となる評価としたとき、SR
より後に発生するu.stop_possible()
やu.stop_requested()
の評価はtrue
であること。stoppable-callback-for<CallbackFn, Token, Initialize>
を満たす任意の型CallbackFn
および型Initialize
が、stoppable-callback-for<CallbackFn, Token, Initializer>
のモデルであること。t
が停止状態を持たない(disengaged)とき、t.stop_possible()
やt.stop_requested()
の評価がfalse
であること。t
とu
が同一の停止状態を参照するか共に停止状態を持たないときt == u
がtrue
であり、それ以外のときはfalse
であること。request_stop
,stop_requested
,stop_possible
メンバ関数の呼び出しはデータ競合を引き起こさない。
ここで、説明専用コンセプトstoppable-callback-for
を以下のように定義する。
template<class CallbackFn, class Token, class Initializer = CallbackFn>
concept stoppable-callback-for =
invocable<CallbackFn> &&
constructible_from<CallbackFn, Initializer> &&
requires { typename stop_callback_for_t<Token, CallbackFn>; } &&
constructible_from<stop_callback_for_t<Token, CallbackFn>, const Token&, Initializer>;
説明用のinit
をsame_as<decltype(init), Initializer>
を満たす式、型SCB
をstop_callback_for_t<Token, CallbackFn>
とする。
stoppable-callback-for<CallbackFn, Token, Initializer>
のモデルとなるには、下記を満たすこと。
- 次のコンセプトのモデルであること。
constructible_from<SCB, Token, Initializer>
constructible_from<SCB, Token&, Initializer>
constructible_from<SCB, const Token, Initializer>
- 説明用の
scb
をSCB
型オブジェクト、callback_fn
をscb
に関連付けられたCallbackFn
型のコールバック関数とする。引数t
とinit
からの直接非リスト初期化scb
は、次のように停止可能コールバック登録(stoppable callback registration)を実行すること。t.stop_possible() == true
のとき、callback_fn
がinit
で直接初期化される。scb
構築が送出する例外は、init
からのcallback_fn
構築で送出された例外のみ。- コールバック呼び出し
std::forward<CallbackFn>(callback_fn)()
は、次のようにt
に関連する停止状態に登録されること。- 登録時点で
t.stop_requested()
がfalse
に評価されるとき、コールバック呼び出しは停止状態のコールバックリストに追加され、停止状態に停止要求が行われたたときにstd::forward<CallbackFn>(callback_fn)()
が評価される。 - そうでなければ、
scb
コンストラクタを実行したスレッド上でstd::forward<CallbackFn>(callback_fn)()
が即時実行され、コールバック呼び出しはリストに追加されない。
- 登録時点で
t.stop_possible() == false
のとき、callback_fn
の初期化によるscb
初期化には要求が課されない。
scb
の破棄は、次のように停止可能コールバック登録解除(stoppable callback deregistration)を実行すること。scb
コンストラクタがt
の停止状態にコールバック呼び出しを登録していなければ、停止可能コールバック登録解除はcallback_fn
破棄以外の効果を持たない。- そうでなければ、関連する停止状態から
callback_fn
の呼び出しが除外されること。 callback_fn
が別スレッド上で並行実行中の場合、当該callback_fn
呼び出しから戻るまで停止可能コールバック登録解除はブロックされる。このcallback_fn
呼び出しからの戻りはcallback_fn
の破棄よりも確実に前に発生する。callback_fn
が現在のスレッド上で実行中の場合、デストラクタはcallback_fn
からの戻りを待機してブロックしてはいけない。- 停止可能コールバック登録解除は、同じ停止状態に登録された他のコールバック呼び出しの完了をブロックしてはいけない。
- 停止可能コールバック登録解除は
callback_fn
を破棄すること。
バージョン
言語
- C++26
処理系
- Clang: ??
- GCC: ??
- ICC: ??
- Visual C++: ??