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から特殊化されたspawn-state型のオブジェクト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(); // exposition only
private:
using alloc-t = // exposition only
typename allocator_traits<Alloc>::template rebind_alloc<spawn-state>;
alloc-t alloc; // exposition only
op-t op; // exposition only
Token token; // exposition only
void destroy() noexcept; // exposition only
};
}
spawn-state(Alloc alloc, Sender&& sndr, Token token);
-
効果 : メンバ変数
allocを引数allocで、メンバ変数tokenを引数tokenで、opを下記で初期化する。
void run();
-
効果 : 下記と等価
if (token.try_associate()) start(op); else destroy();
void complete() noexcept override;
-
効果 : 下記と等価
auto token = std::move(this->token); destroy(); token.disassociate();
void destroy() noexcept;
-
効果 : 下記と等価
auto alloc = std::move(this->alloc); allocator_traits<alloc-t>::destroy(alloc, this); allocator_traits<alloc-t>::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++: ??