C ++でstd :: threadを一時停止および再開するstd :: condition_variableと比較してstd :: atomicを使用するアプローチ

Quantum_Programmer

これは別の質問ですが、ここで尋ねた前の質問に関連しています

私は使用していますstd::thread、私の中でC++は常にいくつかのデータをポーリング&バッファに追加するコード。私が使用してC++ lambda、このようなスレッドを開始します。

StartMyThread() {

    thread_running = true;
    the_thread = std::thread { [this] {
        while(thread_running) {
          GetData();
        }
    }};
}

thread_runningされるatomic<bool>クラス・ヘッダ内で宣言します。ここに私のあるGetData関数は:

GetData() {
    //Some heavy logic
}

次私も持っているStopMyThread、私は設定機能thread_running、それはでしばらくループの外に出たように、falseにしますlambda block

StopMyThread() {
  thread_running = false;
  the_thread.join();
}

私が理解したように、私は一時停止&使用してスレッドを再開することができますstd::condition_variableように尖ったアウトをここに私の以前の質問に。

しかしstd::atomic<bool> thread_runningGetData()以下のようにロジックを実行するだけで実行したり、実行しなかったりすると、デメリットはありますか?

GetData() {
    if (thread_running == false)
      return;
    //Some heavy logic
}

std::condition_variable ここで 説明するようにを使用するアプローチと比較して、これはより多くのCPUサイクルを消費しますか?

Yakk-Adam Nevraumont

条件変数は、別のスレッドを条件付きで停止するかどうかを決定する場合に役立ちます。したがって、実行する必要がないことに気付いたときに待機する、常に実行されている「ワーカー」スレッドがある場合があります。

アトミックソリューションでは、UIインタラクションをワーカースレッドと同期するか、非同期で行うために非常に複雑なロジックが必要です。

一般的なルールとして、あなたのUIの応答スレッドは、ワーカースレッドから非準備状態でブロックすることはありません。

struct worker_thread {
  worker_thread( std::function<void()> t, bool play = true ):
    task(std::move(t)),
    execute(play)
  {
    thread = std::async( std::launch::async, [this]{
      work();
    });
  }
  // move is not safe.  If you need this movable,
  // use unique_ptr<worker_thread>.
  worker_thread(worker_thread&& )=delete;
  ~worker_thread() {
    if (!exit) finalize();
    wait();
  }
  void finalize() {
    auto l = lock();
    exit = true;
    cv.notify_one();
  }
  void pause() {
    auto l = lock();
    execute = false;
  }
  void play() {
    auto l = lock();
    execute = true;
    cv.notify_one();
  }
  void wait() {
    Assert(exit);
    if (thread)
      thread.get();
  }
private:
  void work() {
    while(true) {
      bool done = false;
      {
        auto l = lock();
        cv.wait( l, [&]{
          return exit || execute;
        });
        done = exit; // have lock here
      }
      if (done) break;
      task();
    }
  }
  std::unique_lock<std::mutex> lock() {
     return std::unique_lock<std::mutex>(m);
  }
  std::mutex m;
  std::condition_variable cv;
  bool exit = false;
  bool execute = true;
  std::function<void()> task;
  std::future<void> thread;
};

またはそのような。

これは、スレッドを所有しています。スレッドを繰り返し、それがであるとしてタスクを実行play()モード。あなたの場合はpause()、次の時間task()が終了、ワーカースレッドが停止します。通話が終了するplay()前に、にtask()気付かない場合pause()

唯一の待機は、の破棄ですworker_thread。ここでは、終了する必要があることをワーカースレッドに自動的に通知し、終了するのを待機します。

手動でできる.wait().finalize()にも。.finalize()は非同期ですが、アプリがシャットダウンしている場合は、アプリを早期に呼び出して、メインスレッドが他の場所でクリーンアップしている間、ワーカースレッドにクリーンアップする時間を与えることができます。

.finalize() 取り消すことはできません。

コードはテストされていません。

この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。

侵害の場合は、連絡してください[email protected]

編集
0

コメントを追加

0

関連記事

Related 関連記事

ホットタグ

アーカイブ