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

履歴 編集

customization point object
<execution>

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

namespace std::execution {
  struct spawn_t { unspecified };
  inline constexpr spawn_t spawn{};
}

概要

spawnは、入力Senderに対して非同期トークンスコープへの関連付けを試み、成功時に入力Senderを早期開始(eagerly start)させるSenderコンシューマである。

効果

説明用の式sndr, token, envを下記の通り定義する。

sender<Sndr>, scope_token<Token>, queryable<Env>のいずれかを満たさないとき、呼び出し式spawn(sndr, token, env)不適格となる。

そうでなければ、呼び出し式spawn(sndr, token, env)に対して、説明用の式new_sendertoken.wrap(sndr)とし、allocsenvを次の通りとする。

呼び出し式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を下記で初期化する。

    connect(std::move(sndr), spawn-receiver(this))
    

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;

#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

処理系

関連項目

参照