最終更新日時(UTC):
が更新

履歴 編集

customization point object
<execution>

std::execution::continues_on(C++26)

namespace std::execution {
  struct continues_on_t { unspecified };
  inline constexpr continues_on_t continues_on{};
}

概要

continues_onは、指定Scheduler上で完了させるSenderアダプタである。

continues_onパイプ可能Senderアダプタオブジェクトであり、パイプライン記法をサポートする。

効果

説明用の式schsndrに対して、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)));
      };
  };
}

説明用の式sndrenvに対して、型Sndrdecltype((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_fromSenderへと変換される。

説明用の式out_sndrcontinues_on(sndr, sch)戻り値Senderとし、型OutSndrdecltype((out_sndr))とする。式out_rcvrsender_in<OutSndr, Env> == trueとなる環境Envに関連付けられたReceiverとする。out_sndrout_rcvrとの接続(connect)結果Operation Stateへの左辺値参照をopとしたとき、

  • 呼び出しstart(op)は、現在の実行エージェント上で入力Sendersndrを開始し、Schedulerschに関連付けられた実行リソースに属する実行エージェント上でout_rcvrの完了操作を実行すべき。
  • sch上でのスケジューリングが失敗した場合、未規定の実行エージェント上でout_rcvrエラー完了が行われるべき。

備考

continues_onSenderアルゴリズムの動作は、Receiver接続(connect)時のschedule_fromSenderアルゴリズムへの変換、および説明専用の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

処理系

関連項目

参照