5

すでにキューに入っているすべてのポストされたタスクをクリアするにはどうすればよいio_service::strandですか? ブーストドキュメントから同様の方法は見当たりません。

4

2 に答える 2

8

非同期呼び出しチェーンを適切に設計することで正しく解決できるため、まだその必要性を見つけていません。一般に、Boost.Asio API は、複雑なアプリケーションが非同期フローで複雑にならないように慎重に設計されています。

呼び出しチェーンを調べて、それらを再設計する努力が、ストランドをクリアする複雑さを導入するよりも現在および将来のリスクの方が大きいことを完全に確信している場合は、それを達成する方法があります. strandただし、および関連する内の呼び出されていないハンドラをすべて削除するという大きな副作用がありますio_service

が破棄されるstrandと、そのデストラクタio_serviceは、非並行性の保証を維持しながら、呼び出されていないハンドラーを遅延呼び出し用にスケジュールします。io_service デストラクターは、遅延呼び出しがスケジュールされていた、呼び出されていないハンドラー オブジェクトが破棄されることを示します。strandしたがって、との有効期間を制御するio_serviceことで、ストランド内のハンドラーをクリアできます。

これは、ヘルパー クラスを使用した非常に単純化された例clearable_strandです。

#include <boost/asio.hpp>
#include <boost/bind.hpp>
#include <boost/optional.hpp>
#include <boost/utility/in_place_factory.hpp>

class clearable_strand
{
public:
  clearable_strand(boost::asio::io_service& main_io_service)
    : main_io_service_(main_io_service)
  {
    clear();
  }

public:
  template <typename Handler>
  void post(const Handler& handler)
  {
    // Post handler into the local strand.
    local_strand_->post(handler);

    // Local service now has work, so post its run handler to the
    // main service.
    main_io_service_.post(boost::bind(
      &boost::asio::io_service::run_one, boost::ref(local_io_service_)));
  }

  void clear()
  {
    // Destroy previous (if any).
    local_strand_     = boost::none;
    local_io_service_ = boost::none;
    // Reconstruct.
    local_io_service_ = boost::in_place();
    local_strand_     = boost::in_place(boost::ref(local_io_service_.get()));
  }

private:
  boost::asio::io_service&                 main_io_service_;
  boost::optional<boost::asio::io_service> local_io_service_;
  boost::optional<boost::asio::strand>     local_strand_;
};

のハンドラーのみが破棄されるように効果を最小限に抑えるために、クラスはmain にアタッチするのではなくstrandinternal を使用します。作業が にポストされると、ハンドラーがメインにポストされ、デイジー チェーンが実行され、ローカル にサービスが提供されます。io_servicestrandio_servicestrandio_serviceio_service

そしてその使用法:

void print(unsigned int x)
{
  std::cout << x << std::endl;
}

int main()
{
  boost::asio::io_service io_service;
  io_service.post(boost::bind(&print, 1));

  clearable_strand strand(io_service);
  strand.post(boost::bind(&print, 2));
  strand.post(boost::bind(&print, 3));
  strand.clear(); // Handler 2 and 3 deleted.

  strand.post(boost::bind(&print, 4));
  io_service.run();
}

プログラムを実行すると、 と が出力さ14ます。強調しておきたいのは、これは非常に単純化された例であり、複雑でない方法でスレッド セーフを実現するboost::asio::strandことは困難な場合があるということです。

于 2013-03-05T16:54:15.877 に答える
2

これは不可能です。目的に応じて設計を再構築する必要があります。1 つの可能性は、優先度の高い特定のハンドラーを優先度の低いハンドラーの前に実行したい場合に、優先ハンドラーの例を利用することです。

于 2013-03-04T21:51:39.743 に答える