2012-10-03 46 views
8

該標準規定:「一個thread :: id類型的對象爲所有不代表執行線程的線程對象提供一個不同的值。這是關於operator==的單一/不同值,還是實際按位單一/不同值?對std :: thread :: id的要求。它可以被霧化嗎?

問題的原因:MSVC2012的std::thread::id::id()在其中一個字段中留下垃圾,並且它破壞了在std::atomic<std::thread::id>上進行比較交換的代碼(因爲後者取決於按位比較)。

std::atomic<std::thread::id>法律建設的第一位?

編輯:用於參考,代碼是這樣的:

while(!worker_id.compare_exchange_weak(no_id = thread_id_type(), self_id)) 
    sleep(); 

回答

10

首先,std::atomic<std::thread::id>是合法的: std::thread::id必須是可複製的(30.3.1.1p2),它符合std::atomic<>(29.5p1)的要求。

但是,它是一個不透明的類,因此不要求比較相等的對象的位模式相同。

因此,如果您使用compare_exchange_weakcompare_exchange_strong,那麼對於比較相等的值可能會失敗。

因此,建議是使用在一個循環compare_exchange_weak離開expected值作爲先前迭代的結果。

在你的情況,我從你的循環解釋語義是:不斷循環,而worker_id是另一個線程的ID,或worker_idstd::thread::id換來的卻是失敗。您可以通過以下實現:

no_id=std::thread::id(); 
while((no_id!=std::thread::id()) || 
     !worker_id.compare_exchange_weak(no_id, self_id)){ 
    if(no_id!=std::thread::id()) no_id=std::thread::id(); 
    sleep(); 
} 

no_id=std::thread::id(); 
while(!worker_id.compare_exchange_weak(
      (no_id!=std::thread::id())?(no_id=std::thread::id())?no_id, self_id)) 
    sleep(); 

即只改變no_id值,如果它是不std::thread::id()

+0

謝謝。選擇性地重置'no_id'是個不錯的技巧,現在我開始想知道爲什麼我沒有看到它:) – vpozdyayev

+0

但是,如果「no_id!= std :: thread :: id(),你可能只想調用sleep 「 在循環。 – cmeerw

+0

@cmeerw是的 - 我只是試圖儘可能地複製vpozdyayev的循環。如果'compare_exchange_weak'虛假地「失敗」,那麼你在大多數情況下想立即循環,而不用等待。 –

5

這在LWG924討論。本質上,你不能使用compare_exchange_strong,但你應該可以在循環中使用compare_exchange_weak,例如

expected = current.load(); 
do { 
    desired = function(expected); 
} while (!current.compare_exchange_weak(expected, desired)); 

編輯:強制重置價值擊敗循環的目的 - 根據所提供的代碼,我想,那麼最好的解決辦法是:

no_id = std::thread::id(); 
while(!worker_id.compare_exchange_weak(no_id, self_id)) 
{ 
    if (no_id != std::thread::id()) 
    { 
    sleep(); 
    no_id = std::thread::id(); 
    } 
} 
+0

我在一個循環中使用'compare_exchange_weak',可悲的是,它沒有幫助。順便說一句,這裏的問題是未初始化的字段,而不是填充(在鏈接中提到「相關但可分離的問題」)。我知道關於memcmp語義和compare_exchange_weak快速收斂的註釋29.6.5/26,但是我仍然不知道如果'current'和'expected'是不同的按位表示,每個'operator ==')的值。 – vpozdyayev

+0

向問題添加了代碼示例。 – vpozdyayev

相關問題