namespace std::execution {
struct continues_on_t { unspecified };
inline constexpr continues_on_t continues_on{};
}
概要
continues_on
は、指定Scheduler上で完了させるSenderアダプタである。
continues_on
はパイプ可能Senderアダプタオブジェクトであり、パイプライン記法をサポートする。
効果
説明用の式sch
とsndr
に対して、decltype((sch))
がscheduler
を満たさない、もしくはdecltype((sndr))
がsender
を満たさないとき、呼び出し式continues_on(sndr, sch)
は不適格となる。
そうでなければ、呼び出し式continues_on(sndr, sch)
はsndr
が1回だけ評価されることを除いて、下記と等価。
transform_sender(get-domain-early(sndr), make-sender(continues_on, sch, sndr))
Senderアルゴリズムタグ continues_on
Senderアルゴリズム動作説明用のクラステンプレートimpls-for
に対して、下記の特殊化が定義される。
namespace std::execution {
template<>
struct impls-for<continues_on_t> : default-impls {
static constexpr auto get-attrs =
[](const auto& data, const auto& child) noexcept -> decltype(auto) {
return JOIN-ENV(SCHED-ATTRS(data), FWD-ENV(get_env(child)));
};
};
}
説明用の式sndr
とenv
に対して、型Sndr
をdecltype((sndr))
とする。sender-for<Sndr, continues_on_t> == false
のとき、式continues_on.transform_sender(sndr, env)
は不適格となる。
そうでなければ、式continues_on.transform_sender(sndr, env)
は下記と等価。
auto [_, data, child] = sndr;
return schedule_from(std::move(data), std::move(child));
カスタマイゼーションポイント
Senderアルゴリズム構築時に、Sendersndr
に関連付けられた実行ドメインに対してexecution::transform_sender
経由でSender変換が行われる。
デフォルト実行ドメインでは無変換。
Receiverとの接続(connect)時に、Schedulersch
に関連付けられた実行ドメインに対してexecution::transform_sender
経由でSender変換が行われる。
デフォルト実行ドメインではcontinues_on.transform_sender(out_sndr, env)
が呼ばれ、schedule_from
Senderへと変換される。
説明用の式out_sndr
をcontinues_on(sndr, sch)
の戻り値Senderとし、型OutSndr
をdecltype((out_sndr))
とする。式out_rcvr
をsender_in<OutSndr, Env> == true
となる環境Env
に関連付けられたReceiverとする。out_sndr
とout_rcvr
との接続(connect)結果Operation Stateへの左辺値参照をop
としたとき、
- 呼び出し
start(op)
は、現在の実行エージェント上で入力Sendersndr
を開始し、Schedulersch
に関連付けられた実行リソースに属する実行エージェント上でout_rcvr
の完了操作を実行すべき。 sch
上でのスケジューリングが失敗した場合、未規定の実行エージェント上でout_rcvr
のエラー完了が行われるべき。
備考
continues_on
Senderアルゴリズムの動作は、Receiver接続(connect)時のschedule_from
Senderアルゴリズムへの変換、および説明専用のget-domain-late
関数テンプレートでの特別扱いによって実現される。
例
#include <thread>
#include <print>
#include <execution>
namespace ex = std::execution;
int main()
{
std::println("main#{}", std::this_thread::get_id());
ex::run_loop loop;
std::jthread worker{[&]{
std::println("start worker#{}", std::this_thread::get_id());
loop.run();
}};
ex::scheduler auto sch = loop.get_scheduler();
ex::sender auto sndr =
ex::just(2)
| ex::then([](int n) {
std::println("on main#{}", std::this_thread::get_id());
return n * 3;
})
| ex::continues_on(sch)
| ex::then([](int n) {
std::println("on worker#{}", std::this_thread::get_id());
return n * 7;
});
auto [val] = std::this_thread::sync_wait(std::move(sndr)).value();
std::println("val={}", val);
loop.finish();
}
出力例
main#137071308048192
on main#137071308048192
start worker#137071301756480
on worker#137071301756480
val=42
バージョン
言語
- C++26
処理系
- Clang: ??
- GCC: ??
- ICC: ??
- Visual C++: ??