So beginne ich mich mit C++ 11 <atomic>
Arten vertraut machen. In der Vergangenheit, als ich eine atomare Flagge hatte, würde ich normalerweise einfach einen Mutex sperren, bevor ich darauf zugreife. Eine allgemeine Notwendigkeit wäre, zu überprüfen, ob das Flag false
ist, und wenn ja, setze es atomisch auf true
und dann etwas tun. Also im Grunde wäre dies wie dies erreicht werden, wo flag
ist ein einfaches bool
:Grundlegende Verwendung von Bedingungen mit std :: atomic <T>
{
std::lock_guard<std::mutex> lock(my_mutex);
if (!flag)
{
flag = true;
// do something;
}
}
So, jetzt ich versuche, herauszufinden, wie das gleiche kann mit <atomic>
erreicht werden. Die docs sagen, dass der Zuweisungsoperator und operator T
eines atomaren Typs atomare Operationen sind. Allerdings, wenn ich flag
zu std::atomic<bool>
ändern, ich denke, ich kann nicht einfach sagen:
if (!flag)
{
flag = true;
// do something
}
... weil, obwohl der Ausdruck (!flag)
atomar ist, und die Zuordnung flag = true
ist atomar, gibt es nichts, einen anderen Thread zu verhindern zwischen dem Ändern des Flags zwischen diesen beiden Anweisungen.
Also, wenn ich das richtig hier, die einzige richtige Verwendung verstehen - bei allen - von conditionals mit atomaren Typen, in dem das Ergebnis der bedingten die atomare Variable ändern könnte, ist das verwenden Vergleichs- und Auslagerungsoperation ? Hab ich recht?
Also, ich würde sagen:
bool expected = false;
if (flag.compare_exchange_weak(expected, true))
{
// do something
}
Bin ich in meinem Verständnis korrigieren hier?
['std :: atomic_flag'] (http://en.cppreference.com/w/cpp/atomic/atomic_flag) existiert genau für den Anwendungsfall, den Sie beschreiben, und außerdem ist es garantiert kostenlos auf allen Plattformen. Sie würden die Methode "test_and_set" verwenden, die atomar ist.Sie können auch eine 'std :: atomic' verwenden und einen 'fetch_add' darauf ausführen, der atomar ist und Ihnen den vorherigen Wert zum Zeitpunkt der Inkrementierung gibt (dies ist oft schneller als ein CAS auf den meisten Architekturen, obwohl ich mir nicht schneller vorstelle als 'std :: atomic_flag', was in diesem Fall meine Präferenz wäre). –
Cameron
Richtig - aber es scheint, es gibt keine Möglichkeit, den Wert einer atomaren Flagge einfach atomar "zu überprüfen" (ohne es zu setzen) - oder gibt es? Die Dokumente definieren keine 'operator bool' oder was immer den Ausdruck' if (flag) 'ermöglichen würde. Ich weiß, dass ich diese Anforderung in meiner Frage nicht angegeben habe - ich frage mich nur. Apropos ... warum * gibt es keine Möglichkeit, einfach die atomare Flagge zu überprüfen, ohne sie zu setzen? – Siler
Das ist richtig, Sie müssen es einstellen, um es zu testen (das entspricht Ihrem Beispielcode, wie er derzeit geschrieben wird, außer dass er atomar ist). Wenn Sie es unabhängig testen müssen, schlage ich vor, die 'fetch_add'-Methode oder' compare_exchange_strong' zu verwenden (was viel übersichtlicher ist und [so schnell wie 'fetch_add' (' lock xadd] auf x86] ist (http: // www.agner.org/optimize/instruction_tables.pdf)). – Cameron