namespace std::execution {
struct spawn_t { unspecified };
inline constexpr spawn_t spawn{};
}
概要
spawnは、入力Senderに対して非同期トークンスコープへの関連付けを試み、成功時に入力Senderを早期開始(eagerly start)させるSenderコンシューマである。
効果
説明用の式sndr, token, envを下記の通り定義する。
Sndr型をdecltype((sndr))、Token型をremove_cvref_t<decltype((token))>、Env型をremove_cvref_t<decltype((env))>とする。
sender<Sndr>, scope_token<Token>, queryable<Env>のいずれかを満たさないとき、呼び出し式spawn(sndr, token, env)は不適格となる。
そうでなければ、呼び出し式spawn(sndr, token, env)に対して、説明用の式new_senderをtoken.wrap(sndr)とし、allocとsenvを次の通りとする。
- 式
get_allocator(env)が適格なとき、allocをget_allocator(env)の結果、senvを式envとする。 - そうでなはく、式
get_allocator(get_env(new_sender))が適格なとき、allocをget_allocator(get_env(new_sender))の結果、senvを式JOIN-ENV(prop(get_allocator, alloc), env)とする。 - そうではないとき、
allocをallocator<void>()、senvを式envとする。
呼び出し式spawn(sndr, token, env)はvoid型であり、次の効果をもつ。
allocを用いてメモリ確保し、alloc,write_env(token.wrap(sndr), senv),tokenからdecltype(spawn-state(alloc, write_env(token.wrap(sndr), senv), token))型のオブジェクトoを構築し、o.run()を呼び出す。いずれかのオブジェクト構築・破棄時に例外送出されたときは、確保されたメモリが解放される。
呼び出し式spawn(sndr, token)は、式spawn(sndr, token, execution::env<>())と等価である。
説明専用エンティティ
クラスspawn-state-base
namespace std::execution {
struct spawn-state-base { // exposition only
virtual void complete() noexcept = 0; // exposition only
};
}
クラスspawn-receiver
namespace std::execution {
struct spawn-receiver { // exposition only
using receiver_concept = receiver_t;
spawn-state-base* state; // exposition only
void set_value() && noexcept { state->complete(); }
void set_stopped() && noexcept { state->complete(); }
};
}
クラステンプレートspawn-state
namespace std::execution {
template<class Alloc, scope_token Token, sender Sender>
struct spawn-state : spawn-state-base { // exposition only
using op-t = connect_result_t<Sender, spawn-receiver>; // exposition only
spawn-state(Alloc alloc, Sender&& sndr, Token token); // exposition only
void complete() noexcept override; // exposition only
void run() noexcept; // exposition only
private:
using assoc-t = // exposition only
remove_cvref_t<decltype(declval<Token&>().try_associate())>;
Alloc alloc; // exposition only
op-t op; // exposition only
assoc-t assoc; // exposition only
};
}
spawn-state(Alloc alloc, Sender&& sndr, Token token);
-
効果 : メンバ変数
allocをstd::move(alloc)で、メンバ変数assocをtoken.try_associate()で、メンバ変数opを下記で初期化する。
void run() noexcept;
-
効果 : 下記と等価
if (assoc) start(op); else complete();
void complete() noexcept override;
-
効果 : 下記と等価
auto assoc = std::move(this->assoc); { using traits = allocator_traits<Alloc>::template rebind_traits<spawn-state>; typename traits::allocator_type alloc(this->alloc); traits::destroy(alloc, this); traits::deallocate(alloc, this, 1); }
例
#include <print>
#include <execution>
namespace ex = std::execution;
int main()
{
// システムスレッドプール上の実行タスクを定義
ex::scheduler auto sch = ex::get_parallel_scheduler();
ex::sender auto sndr =
ex::schedule(sch)
| ex::then([](){ std::println("hello async"); });
// 非同期スコープを定義
ex::counting_scope scope;
// タスクを早期開始させる
std::println("spawn");
ex::spawn(std::move(sndr), scope.get_token());
// 非同期スコープを合流
std::println("sync_wait");
std::this_thread::sync_wait(scope.join());
}
出力
spawn
hello async
sync_wait
バージョン
言語
- C++26
処理系
- Clang: ??
- GCC: ??
- ICC: ??
- Visual C++: ??