|
| 1 | +# stoppable_token |
| 2 | +* stop_token[meta header] |
| 3 | +* concept[meta id-type] |
| 4 | +* std[meta namespace] |
| 5 | +* cpp26[meta cpp] |
| 6 | + |
| 7 | +```cpp |
| 8 | +namespace std { |
| 9 | + template<class Token> |
| 10 | + concept stoppable_token; |
| 11 | +} |
| 12 | +``` |
| 13 | +
|
| 14 | +## 概要 |
| 15 | +`stoppable_token`は、型`Token`が停止トークンとしての基本的なインタフェースを提供することを表すコンセプトである。 |
| 16 | +
|
| 17 | +
|
| 18 | +## 要件 |
| 19 | +まず、説明専用クラステンプレート`check-type-alias-exists`を以下のように定義する。 |
| 20 | +
|
| 21 | +```cpp |
| 22 | +template<template<class> class> |
| 23 | +struct check-type-alias-exists; |
| 24 | +``` |
| 25 | + |
| 26 | +`stoppable_token`コンセプトは、以下のように定義される。 |
| 27 | + |
| 28 | +```cpp |
| 29 | +template<class Token> |
| 30 | +concept stoppable_token = |
| 31 | + requires (const Token tok) { |
| 32 | + typename check-type-alias-exists<Token::template callback_type>; |
| 33 | + { tok.stop_requested() } noexcept -> same_as<bool>; |
| 34 | + { tok.stop_possible() } noexcept -> same_as<bool>; |
| 35 | + { Token(tok) } noexcept; |
| 36 | + } && |
| 37 | + copyable<Token> && |
| 38 | + equality_comparable<Token> && |
| 39 | + swappable<Token>; |
| 40 | +``` |
| 41 | +* same_as[link /reference/concepts/same_as.md] |
| 42 | +* copyable[link /reference/concepts/copyable.md] |
| 43 | +* equality_comparable[link /reference/concepts/equality_comparable.md] |
| 44 | +* swappable[link /reference/concepts/swappable.md] |
| 45 | +
|
| 46 | +
|
| 47 | +## モデル |
| 48 | +
|
| 49 | +説明用の変数`t`, `u`を、同一の停止状態を参照する別々な`Token`型ブジェクトとする。 |
| 50 | +型`Token`が以下を満たす場合に限って、型`Token`は`stoppable_token`のモデルである。 |
| 51 | +
|
| 52 | +- `SP`を`t.stop_possible()`が`false`となる評価としたとき、`SP`より後に発生する`u.stop_possible()`や`u.stop_requested()`の評価は`false`であること。 |
| 53 | +- `SR`を`t.stop_requested()`が`true`となる評価としたとき、`SR`より後に発生する`u.stop_possible()`や`u.stop_requested()`の評価は`true`であること。 |
| 54 | +- `stoppable-callback-for<CallbackFn, Token, Initialize>`を満たす任意の型`CallbackFn`および型`Initialize`が、`stoppable-callback-for<CallbackFn, Token, Initializer>`のモデルであること。 |
| 55 | +- `t`が停止状態を持たない(disengaged)とき、`t.stop_possible()`や`t.stop_requested()`の評価が`false`であること。 |
| 56 | +- `t`と`u`が同一の停止状態を参照するか共に停止状態を持たない(disengaged)とき`t == u`が`true`であり、それ以外のときは`false`であること。 |
| 57 | +
|
| 58 | +
|
| 59 | +ここで、説明専用コンセプト`stoppable-callback-for`を以下のように定義する。 |
| 60 | +
|
| 61 | +```cpp |
| 62 | +template<class CallbackFn, class Token, class Initializer = CallbackFn> |
| 63 | +concept stoppable-callback-for = |
| 64 | + invocable<CallbackFn> && |
| 65 | + constructible_from<CallbackFn, Initializer> && |
| 66 | + requires { typename stop_callback_for_t<Token, CallbackFn>; } && |
| 67 | + constructible_from<stop_callback_for_t<Token, CallbackFn>, const Token&, Initializer>; |
| 68 | +``` |
| 69 | +* invocable[link /reference/concepts/invocable.md] |
| 70 | +* constructible_from[link /reference/concepts/constructible_from.md] |
| 71 | +* stop_callback_for_t[link stop_callback_for_t.md.nolink] |
| 72 | + |
| 73 | +説明用の`init`を[`same_as`](/reference/concepts/same_as.md)`<decltype(init), Initializer>`を満たす式、型`SCB`を[`stop_callback_for_t`](stop_callback_for_t.md.nolink)`<Token, CallbackFn>`とする。 |
| 74 | + |
| 75 | +`stoppable-callback-for<CallbackFn, Token, Initializer>`のモデルとなるには、下記を満たすこと。 |
| 76 | + |
| 77 | +- 次のコンセプトのモデルであること。 |
| 78 | + - [`constructible_from`](/reference/concepts/constructible_from.md)`<SCB, Token, Initializer>` |
| 79 | + - [`constructible_from`](/reference/concepts/constructible_from.md)`<SCB, Token&, Initializer>` |
| 80 | + - [`constructible_from`](/reference/concepts/constructible_from.md)`<SCB, const Token, Initializer>` |
| 81 | +- 説明用の`scb`を`SCB`型オブジェクト、`callback_fn`を`scb`に関連付けられた`CallbackFn`型のコールバック関数とする。引数`t`と`init`からの直接非リスト初期化`scb`は、次のように停止可能コールバック登録(stoppable callback registration)を実行すること。 |
| 82 | + - `t.stop_possible() == true`のとき、 |
| 83 | + - `callback_fn`が`init`で直接初期化される。 |
| 84 | + - `scb`構築が送出する例外は、`init`からの`callback_fn`構築で送出された例外のみ。 |
| 85 | + - コールバック呼び出し[`std::forward`](/reference/utility/forward.md)`<CallbackFn>(callback_fn)()`は、次のように`t`に関連する停止状態に登録されること。 |
| 86 | + - 登録時点で`t.stop_requested()`が`false`に評価されるとき、コールバック呼び出しは停止状態のコールバックリストに追加され、停止状態に停止要求が行われたたときに[`std::forward`](/reference/utility/forward.md)`<CallbackFn>(callback_fn)()`が評価される。 |
| 87 | + - そうでなければ、`scb`コンストラクタを実行したスレッド上で[`std::forward`](/reference/utility/forward.md)`<CallbackFn>(callback_fn)()`が即時実行され、コールバック呼び出しはリストに追加されない。 |
| 88 | + - `t.stop_possible() == false`のとき、`callback_fn`の初期化による`scb`初期化には要求が課されない。 |
| 89 | +- `scb`の破棄は、次のように停止可能コールバック登録解除(stoppable callback deregistration)を実行すること。 |
| 90 | + - `scb`コンストラクタが`t`の停止状態にコールバック呼び出しを登録していなければ、停止可能コールバック登録解除は`callback_fn`破棄以外の効果を持たない。 |
| 91 | + - そうでなければ、関連する停止状態から`callback_fn`の呼び出しが除外されること。 |
| 92 | + - `callback_fn`が別スレッド上で並行実行中の場合、当該`callback_fn`呼び出しから戻るまで停止可能コールバック登録解除はブロックされる。この`callback_fn`呼び出しからの戻りは`callback_fn`の破棄よりも確実に前に発生する。 |
| 93 | + - `callback_fn`が現在のスレッド上で実行中の場合、デストラクタは`callback_fn`からの戻りを待機してブロックしてはいけない。 |
| 94 | + - 停止可能コールバック登録解除は、同じ停止状態に登録された他のコールバック呼び出しの完了をブロックしてはいけない。 |
| 95 | + - 停止可能コールバック登録解除は`callback_fn`を破棄すること。 |
| 96 | + |
| 97 | + |
| 98 | +## バージョン |
| 99 | +### 言語 |
| 100 | +- C++26 |
| 101 | + |
| 102 | +### 処理系 |
| 103 | +- [Clang](/implementation.md#clang): ?? |
| 104 | +- [GCC](/implementation.md#gcc): ?? |
| 105 | +- [ICC](/implementation.md#icc): ?? |
| 106 | +- [Visual C++](/implementation.md#visual_cpp): ?? |
| 107 | + |
| 108 | + |
| 109 | +## 関連項目 |
| 110 | +- [`unstoppable_token`](unstoppable_token.md) |
| 111 | +- [`stop_token`](stop_token.md) |
| 112 | +- [`inplace_stop_token`](inplace_stop_token.md.nolink) |
| 113 | +- [`never_stop_token`](never_stop_token.md.nolink) |
| 114 | + |
| 115 | + |
| 116 | +## 参照 |
| 117 | +- [P2300R10 `std::execution`](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/p2300r10.html) |
0 commit comments