2013-04-24 68 views
8

我有一個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的複製構造函數一次,並且它只是移動構造函數一次。而且我也不能保證副本和移動只相當於副本。此外,用戶提供的容器可能是奇怪的,可複製但不可移動,這也會導致這種方法有問題。

那麼,我該怎麼辦?

回答

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

應該工作。

+0

你認爲應該總是這樣做嗎? – 0x499602D2 2013-04-24 22:14:51

+0

@ 0x499602D2其實,我認爲應該避免這種情況。我不太瞭解你的實際情況,或者你正在嘗試解決的問題,並提出其他解決方案,但我知道我從來沒有真正使用過這樣的東西。事實上,我無法真正想到在線程之間複製容器的情況。 – 2013-04-24 23:07:47

1

鎖定,創建內容的副本,然後與成員交換。至少這是最簡單和恕我直言的最乾淨的方式。另一個不太乾淨的方法是使用逗號運算符:(a, b)產生b,但如果a是作用域鎖定,則該臨時對象將保留到下一個序列點,即直到您使用b初始化本地副本。

這就是說,都需要考慮兩件事情:

  • 也許,不能複製反正這樣一個聰明的想法和你的設計作品,以及如果你只是不能進行復印。
  • 如果您有權訪問隊列並且可以讀取它進行復制,那麼這是不是意味着互斥鎖必須已被鎖定?如果不是,你怎麼確定你真的想複製隊列?我不懷疑有什麼答案可以證明設計的合理性,但這是不尋常的。