2016-04-25 3 views
0

Wie ist std::atomic<>compare_exchange() verwandt und übersetzt in/von MS InterlockedCompareExchange64 auf einem nicht atomaren Wert? Gibt es Leistungs- oder Semantik-Unterschiede?InterlockedCompareExchange64 vs Std :: atomic compare_exchange

Zum Beispiel, sind diese Codes gleichwertig?

bearbeiten: David Haim wies darauf hin, dass es int64_t atomic_inc_ms(volatile int64_t& val, int64_t less_than)

gewesen sein sollte
int64_t atomic_inc_ms(int64_t& val, int64_t less_than) { 
int64_t new_val; 
int64_t old_val = val; 
while(true) 
{ 
    if (old_val > less_than) return old_val; 
    new_val = old_val + 1; 
    int64_t got_val = InterlockedCompareExchange64(&val,new_val,old_val); 
    if(got_val == old_val) break; 
    old_val = got; 
} 

return new_val; 
} 

und

int64_t atomic_inc(std::atomic<int64_t>& val, int64_t less_than) { 
int64_t new_val; 
int64_t old_val = val.load(); 
do 
{ 
    if (old_val > less_than) return old_val; 
    new_val = old_val + 1; 
} while (!val.compare_exchange_weak(old_val, new_val)); 

return new_val; 
} 

Ein Anliegen ist die Linie int64_t old_val = val; ohne explizite Atom Last.

Das Beispiel ist das von Is there atomic increment with the check preconditions, that the atomic value was less than the specified value? und ist in der Nähe des Lehrbuchbeispiels zur Verwendung von compare_exchange_weak.

Sind compare_exchange_weak und compare_exchange, semantisch äquivalent zu InterlockedCompareExchangeAcquire64 und InterlockedCompareExchange64?

+1

beide kompilieren zu der gleichen Sache, aka 'lock inc [ptr]', also keine Sorgen. aber Ihr Code zeigt, warum der Standard besser ist, Ihr "val" ist nicht flüchtig, während "Interlocked *" volatile Variable erfordert. Sie müssen nicht darüber nachdenken, wenn Sie "atomar" verwenden. plus die Protabilität –

+0

@DavidHaim. Vielen Dank! Ich stimme zu 100% zu%. Du hast mich geschlagen, um das zu erkennen, während ich SergeyA's Antwort kommentierte. Ich hatte eine unklare Vorstellung davon, was der Compiler mit val machen kann. –

+0

@DavidHaim, verstehe ich dich richtig (die Bearbeitung, die ich gemacht habe, jetzt 'volatile int64_t & val'). –

Antwort

1

Diese Codes sind semantisch gleichwertig. Keine atomare Last für int64_t ist hier von Bedeutung, da Interlocked* Familie Funktionen Hinweis X86, wo alle Lasten atomar sind.

Es besteht die Möglichkeit, dass sich C++ - Atome etwas schneller als Interlocked*-Funktionen verhalten, da der Compiler direkten ASM-Aufruf erzeugt, anstatt eine Funktion aufzurufen. Der Compiler könnte jedoch auch die Funktion Interlocked* erkennen.

+0

Ok. Groß! Und, mein Code 'int64_t old_val = val;'. Es besteht keine Notwendigkeit für flüchtige oder andere Marker, die Val von anderen Thread geändert werden kann? Vielleicht "volatil int64_t & val"? –

0

Std :: Atom ist C++ Standard. Es handelt sich um portablen Code, der mit jedem kompatiblen Compiler kompiliert wird

Interlocked * sind Windows-spezifische Funktionen von Windows SDK. Daher wird dieser Code nicht tragbar sein.

+0

Danke. Das stimmt, aber ich beantworte keine der Fragen, die ich bezüglich der Semantik hatte. –

+0

AFAIK wären diese Unterschiede wahrscheinlich zu gering zum Messen – Ghostrider