最終更新日時(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から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);

  • 効果 : メンバ変数allocstd::move(alloc)で、メンバ変数assoctoken.try_associate()で、メンバ変数opを下記で初期化する。

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

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

処理系

関連項目

参照