簡體   English   中英

如何在初始化列表中鎖定互斥鎖?

[英]How can I lock a mutex in an initializer list?

我有一個ConcurrentQueue類,它基於用戶提供的容器,帶有這樣的構造函數...

ConcurrentQueue(const ConcurrentQueue& other) : m_Queue(other.m_Queue) {}

但是,我需要在復制時鎖定other的互斥鎖。

選項1:

所以我根本不能使用復制構造函數,並且......

ConcurrentQueue(const ConcurrentQueue& other) : m_Queue(other.m_Queue)
{
    std::lock_guard<std::mutex> lock(other.m_Mutex);
    m_Queue = other.m_Queue;
}

但我不能保證復制分配和復制構造是等效的功能。

選項2:

我可以有私人方法......

std::queue<T, Container> GetQueue() const
{
    std::lock_guard<std::mutex> lock(other.m_Mutex);
    return m_Queue;
}

然后在構造函數中執行此操作...

ConcurrentQueue(const ConcurrentQueue& other) : m_Queue(other.GetQueue()) {}

但這可能(取決於優化)使用m_Queue的復制構造函數一次,它移動構造函數一次。 我也不能保證副本和移動只相當於副本。 此外,用戶提供的容器可能是奇怪的並且是可復制的但是不可移動的,這也會導致這種方法出現問題。

那么,我該怎么辦?

ConcurrrentQueue::ConcurrrentQueue(
        ConcurrrentQueue const& other )
    : m_Queue( (std::lock_guard<std::mutex>( other.m_Mutex ),
               other.m_Queue ) )
{
}

應該管用。

鎖定,創建內容的副本,然后將其與成員交換。 至少那是最簡單和恕我直言最干凈的方式。 另一個不太干凈的方法是使用逗號運算符: (a, b)產生b ,但如果a是一個范圍鎖,臨時將一直存在直到下一個序列點,即直到你用b來初始化本地副本。

也就是說,有兩件事需要考慮:

  • 也許復制不是一個聰明的想法,如果你只是禁用復制,你的設計也可以。
  • 如果您可以訪問隊列並且可以將其讀取以進行復制,那是否意味着必須已鎖定互斥鎖? 如果沒有,您如何確定要真正復制隊列? 我不懷疑有答案證明設計合理,但這是不尋常的。

暫無
暫無

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

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