簡體   English   中英

在C ++ 11中的std :: thread exit上自動調用函數

[英]Invoking a function automatically on std::thread exit in C++11

我想設置一個函數(或lambda函數)的調用,以便在當前線程退出時自動發生,但是除非我接管整個線程創建任務,否則我看不到任何與std::thread工作的方法。或者手動確保每個線程調用一些我總是提供的特定函數作為它的最后一個操作。

基本上,我想要的功能,其原型可能類似於這樣的東西:

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

當調用on_thread_exit的線程最終終止時,將執行必要的設置以確保自動調用給定函數,並且不需要在創建線程或終止時顯式調用任何特定函數。

你可以使用thread_local存儲來完成它,因為C ++ 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()來使用它,這將創建退出對象,該對象將以與放入線程隊列相反的順序運行您的函數(可以根據需要隨意修改)。

這是基於Dave S解決方案的簡化/縮短版本,該解決方案使用具有以下屬性的更多C ++ 11功能:

  • 由於ThreadExiter只使用一次,我們可以組合變量聲明,避免public / privateclassstruct )並刪除復制構造函數/賦值運算符
  • std::stack替換為基於范圍的for循環和std::deque
  • 直接添加到成員變量而不是add()方法

請注意,只有在調用了所有調用函數之后才會從std::deque回調函數,這可能是您想要的,也可能不是 - 如果您需要在調用之后(以及之前的任何其他函數對象)將其銷毀函數對象被調用),使用堆棧和pop元素,如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));
}

您可以使用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

   ...
}

我留給你推斷任何線程!

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM