9

std::thread現在のスレッドが終了したときに関数 (またはラムダ関数) の呼び出しが自動的に行われるように設定したいのですが、スレッド作成のタスク全体を引き継ぐか、手動で確認しない限り、それを行う方法がわかりません。すべてのスレッドは、私が常に最後の操作として提供する特定の関数を呼び出します。

基本的に、プロトタイプが次のようなものに似ている関数が必要です。

on_thread_exit(const std::function<void()> &func);

これは、on_thread_exit を呼び出したスレッドが最終的に終了したときに特定の関数が自動的に呼び出されるようにするために必要なセットアップを実行し、スレッドの作成または終了時に特定の関数を明示的に呼び出す必要はありません。

4

3 に答える 3

23

thread_localC++11 はスレッドの終了後にデストラクタを呼び出す必要があるため、ストレージを使用して実行できます。それを適切にサポートするコンパイラがあることを確認する必要があります。

#include <stack> 
#include <function>

void on_thread_exit(std::function<void()> func)
{
  class ThreadExiter
  {
    std::stack<std::function<void()>> exit_funcs;
  public:
    ThreadExiter() = default;
    ThreadExiter(ThreadExiter const&) = delete;
    void operator=(ThreadExiter const&) = delete;
    ~ThreadExiter()
    {
      while(!exit_funcs.empty())
      {
        exit_funcs.top()();
        exit_funcs.pop();
      }
    }
    void add(std::function<void()> func)
    {
      exit_funcs.push(std::move(func));
    }   
  };

  thread_local ThreadExiter exiter;
  exiter.add(std::move(func));
}

基本的に、この関数はthread_local上記のクラスのオブジェクトを作成します。これは、スレッドの終了時に破棄されることを除いて、基本的に静的です。呼び出されると、関数をベクターにプッシュし、破棄されると関数を実行します。

任意のスレッドから呼び出して使用できます。これによりon_thread_exit()、終了オブジェクトが作成され、スレッド キューに入れられたのとは逆の順序で関数が実行されます (必要に応じて自由に変更してください)。

于 2013-11-21T04:40:33.147 に答える
6

これは、次のプロパティを持つより多くの C++11 機能を使用する Dave S のソリューションに基づく簡略化/短縮バージョンです。

  • ThreadExiterは 1 回しか使用されないため、変数宣言を結合し、/ ( to ) を避け、publicコピーprivateコンストラクclassターstruct/代入演算子を削除できます。
  • std::stack範囲ベースの for ループに置き換えて、std::deque
  • add()メソッドを持つ代わりに、メンバー変数に直接追加します

これは、すべてが呼び出された後にのみコールバック関数を破棄することに注意してください。これstd::dequeは、関数オブジェクトが呼び出された後 (および他の関数オブジェクトが呼び出される前) に破棄される必要がある場合に必要な場合とそうでない場合があります。 )、Daveのソリューションのようにスタックとポップ要素を使用します)。

コード:

#include <functional>
#include <deque>

void
on_thread_exit(std::function<void()> func)
{
    thread_local struct ThreadExiter {
        std::deque<std::function<void()>> callbacks;

        ~ThreadExiter() {
            for (auto &callback: callbacks) {
                callback();
            }
        }
    } exiter;

    exiter.callbacks.emplace_front(std::move(func));
}
于 2017-04-25T10:03:51.453 に答える
1

BOOST_SCOPE_EXITを使用できます

メインスレッドの場合:

void on_thread_exit();

void main( int argc, char** argv )
{
   BOOST_SCOPE_EXIT() // may be one arg, at least, is required 
   {
      on_thread_exit();
   }BOOST_SCOPE_EXIT_END

   ...
}

どんなスレッドでも外挿するのはあなたに任せます!

于 2013-11-21T08:30:33.533 に答える