2013-07-05 21 views
0

我很清楚,這不是一個問題,而是更多的討論,但我相信可以提供一個或多個答案,所以在這裏。std:mutex'es作爲將進入容器的對象的成員?

我有像這樣

class MyAwesomeObject { 
public: 
    std::mutex theListMutex; 
    std::list<int> theList; 
}; 

類現在,我相信意圖是比較明顯的,並且例子是故意的學術 - 雖然不是從我的現實遠 - 所以讓我們先走一步。然後我的應用程序處理大量這樣的對象,所有這些對象都存儲在其他地方的矢量中,並且一切都很好。麻煩從我編譯開始。我使用VS2012但我相信其他的編譯器可能會發出類似的錯誤:

error C2248: 'std::mutex::mutex' : cannot access private member declared in class 'std::mutex' 
1>   c:\program files\microsoft visual studio 11.0\vc\include\mutex(116) : see declaration of 'std::mutex::mutex' 
1>   c:\program files\microsoft visual studio 11.0\vc\include\mutex(107) : see declaration of 'std::mutex' 
1>   This diagnostic occurred in the compiler generated function 'MyApp::MyAwesomeObject ::MyAwesomeObject (const MyApp::MyAwesomeObject &)' 

這意思很清楚,我通過很多其他的問題,在經歷在這裏SO,所有這些基本上可以說,「互斥體可以不會被複制「,我很好。所以我到目前爲止的策略是使互斥鎖shared_ptr<mutex>並與它做到。唯一的「缺點」是,現在當我訪問互斥鎖時,我必須使用愚蠢的解引用語法,這當然不是愚蠢的,只是在我使用的所有其他點符號之間有點尷尬和突出這個地方。

現在,在我的問題:使用共享指針解決問題的正確方法?可能我使用了一個唯一的指針,因爲據我所知,我沒有將所有權轉讓給其他任何人(除非在對象成員的指針上調用方法實際上是一種所有權轉移的形式)?還有其他方法可以解決無法複製互斥鎖的事實嗎?

+0

你在做什麼創造了這個錯誤?互斥量不應該永遠需要被複制。如果您處於這種情況,您的設計需要審查。 –

+0

我有一個這樣的對象的向量,並且這個向量由它自己的互斥體保護。正如您所看到的,MyAwesomeObject類的每個對象都包含一個需要使用互斥鎖保護的列表。現在,我的應用程序需要隨機訪問所述矢量,挑選其中一個對象,訪問其列表,在其上執行一些操作,以及對象,然後將對象存儲回來。此外,我還使用基於範圍的循環訪問矢量,我認爲使用的引用不應該創建副本,但我已經完成了一些測試並且似乎發生了一些複製。 – Morpheu5

+0

使它成爲'shared_ptr '的向量,它允許您在對象中擁有不可複製的互斥體。不要去分享互斥,那是壞的。 –

回答

2

所以我的策略迄今已使互斥體shared_ptr<mutex>

等待。爲什麼互斥體會在不同的實例中共享?你是否意識到這最終會通過相同的互斥鎖保護多個theList

你不能只是放下shared_ptr的事情,並假裝它解決的事情。在這種情況下,它改變了語義。我期望這裏的正確語義是:每個新的MyAwesomeObject對象都有自己的互斥體來保護它自己的theList

+0

我同意你的前兩個段落,但第三個有一個問題。這種'distinct_lock'的使用不會導致在複製其他數據成員期間獲取互斥體。大多數情況下,您希望能夠複製互斥鎖安全對象(這種情況相當少見),但您也希望在執行復制時鎖定數據。 –

+0

@DaveS嗯,非常好的一點。然後我會繼續並建議'unique_lock'。呃,不,這仍然不好。哇,真是一團糟。 –

+0

嚴。你的回答向我澄清了一些事情,謝謝。但是我看不出如何使'distinct_lock'結構對我有所幫助。不,等等,我清楚地看到它,我只是因爲它不在標準庫中而感到困惑。我敢肯定,儘管我看不到一種標準功能,但它一定有一種方法可以處理標準功能。至於私人/公共事物:是的,我知道。如果我正在編寫其他可能會在未來看到/使用的代碼,那麼我很可能會採用私有/ getter方法。 – Morpheu5

0

不需要shared_ptr,因爲永遠不會有多個互斥量的所有者。

我會使用std::unique_ptr<std::mutex>,它使您的對象只能移動,不可複製,但這可以將它們存儲在vector。這樣,您可以將列表和相關互斥鎖的所有權從一個對象轉移到另一個對象,但不能複製它們。

這意味着你的MyAwesomeObject將有一個空的「移出」狀態,它沒有互斥體,因此它的列表不應該被使用。你應該添加一個成員查詢它是否是在該州或沒有,這樣用戶就可以知道,如果他們已經被賦予一個空的對象,而一個互斥體:

class MyAwesomeObject { 
    std::unique_ptr<std::mutex> theListMutex; 
    std::list<int> theList; 

public: 
    bool valid() const { return (bool)theListMutex; } 
}; 
+0

這首先破壞了沒有指針向量的整個目的。 – Morpheu5

+0

爲什麼?什麼是「沒有指針向量的全部目的」? –

0

互斥戰略應該基於「交易的範圍「的概念,而不是每個對象/或這個。每一個。

現在事務的範圍可以是

  • 答:操縱單個共享數據結構說列表等
  • B:操縱多個共享數據結構說多個列表中,計數器&等
  • C:操作多個共享數據結構&共享extrenal [可能是文件描述符或db連接等] 資源
+0

這有何幫助?我遇到了情況B,並且我沒有看到該對象內部存在互斥體,這違反了交易原則的範圍。 – Morpheu5

+0

@ Morpheu5我說的是一般指導性提示。如果你閱讀原始問題,用戶正在討論爲每個對象創建互斥鎖。 現在我想說的是它不是關於對象,而是一個'事務',它可能只是一個操作對象內的共享屬性或更大的數據結構的小代碼。 –

+0

我的意思不是粗魯,但如果你讀了原始問題,你會發現我是OP,而且我的意思是說你的回答並沒有讓我更接近解決我的問題。問題。 – Morpheu5

2

不,使用std::shared_ptr不是正確的方法來處理這個問題。

如果你希望你的對象是可複製的,那麼定義一個複製構造函數來鎖定源代碼中的互斥鎖,然後複製這些內容。 Mike Spertus爲我的博客寫了一篇關於此的留言:http://www.justsoftwaresolutions.co.uk/threading/thread-safe-copy-constructors.html

如果你只想讓你的對象可移動(就像喬納森指出的那樣,只需將它存儲在向量中),那麼你可以要麼像上面那樣定義移動構造函數,要麼遵循Jonathan關於使用std::unique_ptr<std::mutex>的建議。

0

另一種可能性是使用的vector代替dequelist,因爲它不強加它存儲的類型的可移動的/可複製的要求(假設使用emplace_*方法構造以存儲在容器中的元件,並且你當然不會複製容器)。

相關問題