atomic_fetch_add, atomic_fetch_add_explicit
| Definiert im Header <stdatomic.h> |
||
| C atomic_fetch_add( volatile A* obj, M arg ); |
(1) | (seit C11) |
| C atomic_fetch_add_explicit( volatile A* obj, M arg, memory_order order ); |
(2) | (seit C11) |
Atomar ersetzt den Wert, auf den von obj gezeigt wird, durch das Ergebnis der Addition von arg zum alten Wert von obj und gibt den Wert zurück, den obj zuvor enthielt. Die Operation ist eine Lese-Änder-Schreib-Operation. Die erste Version ordnet Speicherzugriffe gemäß memory_order_seq_cst, die zweite Version ordnet Speicherzugriffe gemäß order.
Dies ist eine generische Funktion, die für alle atomaren Objekttypen A definiert ist. Das Argument ist ein Zeiger auf einen volatilen atomaren Typ, um Adressen von sowohl nicht-volatilen als auch volatilen (z. B. speicherprogrammierter I/O) atomaren Objekten zu akzeptieren, und die volatile Semantik wird bei der Anwendung dieser Operation auf volatile atomare Objekte beibehalten. M ist entweder der nicht-atomare Typ, der zu A korrespondiert, wenn A ein atomarer ganzzahliger Typ ist, oder ptrdiff_t, wenn A ein atomarer Zeigertyp ist.
Es ist nicht spezifiziert, ob der Name einer generischen Funktion ein Makro oder ein mit externer Bindung deklarierter Bezeichner ist. Wenn eine Makrodefinition unterdrückt wird, um auf eine tatsächliche Funktion zuzugreifen (z. B. in Klammern wie (atomic_fetch_add)(...)) oder ein Programm einen externen Bezeichner mit dem Namen einer generischen Funktion definiert, ist das Verhalten undefiniert.
Für vorzeichenbehaftete Ganzzahltypen ist die Arithmetik so definiert, dass sie die Zweierkomplementdarstellung verwendet. Es gibt keine undefinierten Ergebnisse. Für Zeigertypen kann das Ergebnis eine undefinierte Adresse sein, aber die Operationen haben ansonsten kein undefiniertes Verhalten.
Inhalt |
[bearbeiten] Parameter
| obj | - | Zeiger auf das zu modifizierende atomare Objekt |
| arg | - | Der Wert, der zum Wert im atomaren Objekt addiert werden soll |
| Reihenfolge | - | Die Speicher-Synchronisierungsordnung für diese Operation: alle Werte sind zulässig |
[bearbeiten] Rückgabewert
Der zuvor vom atomaren Objekt, auf das obj zeigt, gehaltene Wert.
[bearbeiten] Beispiel
#include <stdio.h> #include <threads.h> #include <stdatomic.h> atomic_int acnt; int cnt; int f(void* thr_data) { for(int n = 0; n < 1000; ++n) { atomic_fetch_add_explicit(&acnt, 1, memory_order_relaxed); // atomic ++cnt; // undefined behavior, in practice some updates missed } return 0; } int main(void) { thrd_t thr[10]; for(int n = 0; n < 10; ++n) thrd_create(&thr[n], f, NULL); for(int n = 0; n < 10; ++n) thrd_join(thr[n], NULL); printf("The atomic counter is %u\n", acnt); printf("The non-atomic counter is %u\n", cnt); }
Mögliche Ausgabe
The atomic counter is 10000 The non-atomic counter is 9511
[bearbeiten] Referenzen
- C17-Standard (ISO/IEC 9899:2018)
- 7.17.7.5 Die generischen Funktionen atomic_fetch und modify (S. 208)
- C11-Standard (ISO/IEC 9899:2011)
- 7.17.7.5 Die generischen Funktionen atomic_fetch und modify (S. 284-285)
[bearbeiten] Siehe auch
| atomare Subtraktion (Funktion) | |
| C++ Dokumentation für atomic_fetch_add, atomic_fetch_add_explicit
| |