2012-10-03 21 views
8

Standart diyor ki: "Bir tür iş parçacığı :: id öğesi ... bir iş parçacığı temsil etmeyen tüm iş parçacığı nesneleri için tek bir ayrı değer sağlar". Bu operator== ile ilgili tek/ayrı bir değer mi, yoksa gerçek bitsel tek/ayrı değer mi?std :: thread :: id. Gereksinimleri. Atomize olabilir mi?

Sorunun nedeni: MSVC2012'nin std::thread::id::id() alanlarından birinde çöp bırakır ve bir std::atomic<std::thread::id> (sonuncusu bitwise karşılaştırmalara bağlı olduğu için) karşılaştırmasıyla eşleşen bir kod kopyalar.

std::atomic<std::thread::id> öncelikle yasal bir yapı mıdır?

DÜZENLEME: referans için, kod şöyledir:

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

cevap

10

Öncelikle, std::atomic<std::thread::id> yasaldır: std::thread::id, std::atomic<> (29.5p1) gereksinimlerini karşılayan önemsiz olarak kopyalanabilir (30.3.1.1p2) olmalıdır. Bununla birlikte, bu bir opak sınıftır, dolayısıyla eşitliği karşılaştıran nesnelerin bit modelinin özdeş olması gerekmemektedir.

Sonuç olarak, compare_exchange_weak veya compare_exchange_strong kullanırsanız, eşit olan değerler için başarısız olabilir.

Böylece, tavsiye önceki yinelemede sonucunda expected değeri ayrılan bir döngüde compare_exchange_weak, kullanmaktır. Senin durumunda

, ben Döngünüzden yorumlamak semantik şunlardır: worker_id iken döngü devam başka bir iş parçacığı kimliğidir veya worker_idstd::thread::id ama değişimi başarısız oldu. Bunu şu şekilde elde edebilirsiniz: o değilstd::thread::id() ise

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(); 
} 

veya

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(); 

sadece no_id değerini değiştirmek yani.

+0

Teşekkür ederim.Seçmeli 'no_id' sıfırlama güzel bir hiledir, şimdi neden görmediğimi merak etmeye başladım :) – vpozdyayev

+0

Ama muhtemelen uyku aramak istersen "no_id! = Std :: thread :: id() " döngüde. – cmeerw

+0

@cmeerw Evet --- sadece vpozdyayev'in döngüsünü olabildiğince yakından kopyalamaya çalışıyordum. Eğer "compare_exchange_weak", "yanlış" başarısız olursa, çoğu durumda siz beklemeden hemen döngü yapmak istersiniz. –

5

Bu LWG924 tartışılmıştır. Esasen, compare_exchange_strong kullanamazsınız, ancak bir döngüde compare_exchange_weak kullanabilmeniz gerekir, ör.

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

Düzenleme: Kayıtsız şartsız değerini sıfırlama döngü amacı yendi - sağlanan koduna dayalı, ben en iyi çözüm sonra olacağını düşünüyorum:

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

Döngüde 'compare_exchange_weak' kullanıyorum ve ne yazık ki yardımcı olmuyor. Btw, burada sorun başlatılmamış alanlar, doldurma değil (bağlantınızda "ilgili ama ayrılabilir bir sorun" olarak anılacaktır). Memcmp semantiği ve compare_exchange_weak ile ilgili yakınsama notu 29.6.5/26'nın bilincinde olduğumu biliyorum, ancak hala 'current' ve 'beklenen' bit'lerin aynı şekilde farklı temsillerinin nasıl işlediğini göremiyorum. operatör başına == ') değer. – vpozdyayev

+0

Soruya kod örneği eklendi. – vpozdyayev

İlgili konular