簡體   English   中英

使用 boost::signals2::scoped_connection object 作為 class 的成員來實現自動連接壽命是否安全?

[英]Is it safe to use a boost::signals2::scoped_connection object as member of a class for automatic connection lifetime?

我想知道以下代碼是否安全,因為信號可能由不同的線程觸發:

using IntSignal = boost::signals2::signal<void(int)>;

class Foo
{
public:

  Foo(IntSignal& signal)
    : some_resource(new int(0))
  {
    scoped_connection = signal.connect([this](int i) { some_action(i); });
  }

  ~Foo()
  {
    delete some_resource;
  }

private:

  void some_action(int i)
  {
    *some_resource = i;
  }

  int* some_resource;

  boost::signals2::scoped_connection scoped_connection;
}

編輯:為some_action添加了一個虛構的資源、析構函數和一個實現,以使其更加清晰。 有了這個問題,我想澄清一下我的假設是否正確,即信號槽可能在Foo的析構函數之后但在scoped_connection的析構函數之前調用。 為簡潔起見,我省略了保護some_resource的互斥鎖,但是,它與問題無關。

盡管Foo實例被銷毀時連接將被斷開,但在Foo自己的析構函數調用和Foo成員的銷毀之間可能存在微小的差距。 如果資源被破壞后在some_action中使用,這可能會更成問題。

我應該使用普通連接並在Foo的析構函數中斷開它們嗎? scoped_connection成員作為 class 的最后一個成員(應該首先被銷毀)並省略任何銷毀邏輯是否安全?

你是對的,如果在信號運行和訪問some_resource時調用Foo的析構函數,則可能存在競爭。

一個安全的解決方案是在插槽運行時延長Foo的壽命:

class Foo : public std::enable_shared_from_this<Foo>
{
public:

  Foo(IntSignal& signal)
    : some_resource(new int(0))
  {        
      // moved connection initialization to a method since weak_from_this will  
      // be empty inside the constructor. It is initialized only afterwards.
      // It also make sense to connect your signal only after object
      // is fully initialized
  }

  void InitConnection()
  {
     auto weak_self = weak_from_this(); 
     scoped_connection = signal.connect(
       [weak_self](int i) 
      { 
         if (auto self = weak_self.lock())
         {
            // we managed to promote weak_self to a shared_ptr, 'this' will be alive 
            // as long as this scope lives
            some_action(i); // safe
         }
      });

  }

  ~Foo()
  {
     // will only be invoked after Foo's reference count drops to zero.
     // not during the signal is emitted
     delete some_resource; 
  }

private:    
  void some_action(int i)
  {
    *some_resource = i;
  }

  int* some_resource;    
  boost::signals2::scoped_connection scoped_connection;
}

筆記:

  1. enable_shared_from_thisweak_ptr初始化為“this”。 對於您描述的情況,這是一個很好的工具。 在這里查看更多。
  2. 確保將 Foo 創建為shared_ptr ,否則 weak_from_this 將不起作用。 請記住: Foo 在 2 個線程之間共享

暫無
暫無

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

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