Na http://en.cppreference.com/w/cpp/atomic/atomic_compare_exchange następujący przykład kodu jest przedstawiony jako przykład wykorzystania std::atomic_compare_exchange_weak
:Czy kod przykładowy dla atomic_compare_exchange_weak w cppreference jest poprawny?
void append(list* s, node* n)
{
node* head;
do {
head = s->head;
n->next = head;
} while(! std::atomic_compare_exchange_weak(s->head, head, n));
}
Rozumiem, że to ma wpływ porównywanie *(s->head)
z head
, kiedy to, w co wierzę jest pożądany jest porównanie s->head
z head
. Czy pierwszy argument do std::atomic_compare_exchange_weak
w tym przykładzie powinien być &(s->head)
, czy też czegoś mi brakuje?
UPDATE: spec std::atomic_compare_exchange_weak
mówi:
bool atomic_compare_exchange_weak(volatile A* object, C * expected, C desired) noexcept;
bool atomic_compare_exchange_weak(A* object, C * expected, C desired) noexcept;
Efekty: atomowo, porównuje zawartość pamięci wskazywanego przez obiekt ... na równi z oczekiwać, że w ...
wziąłem to oznaczać, że *object
porównano z expected
, ale dalsze badania sugerują, że sama treść jest to, że *object
jest porównywany z *expected
(tj., że "w expected
" oznacza "wskazany przez expected
"). Sugerowałoby to, że odpowiedź na moje pierwotne pytanie brzmi "nie, nie ma potrzeby, aby przyjmować adres s->head
w przykładowym kodzie na cppreference". Ale fakt, że object
musi wskazywać na std::atomic<T>
i powinien wskazywać na T
sprawia, że trudno jest mi wymyślić, jak poprawić kod przy cppreference, aby został skompilowany. Chcemy porównać nagłówek listy z kopią nagłówka listy, ale jeśli nagłówek listy ma typ std::atomic<T>*
, kopia musi być typu T*
, jeśli połączenie ma się składać z std::atomic_compare_exchange_weak
, i Nie mogę znaleźć sposobu przypisania std::atomic<T>*
do T*
bez numeru reinterpret_cast
. Nawet wtedy trzeci parametr do std::atomic_compare_exchange_weak
musiałby być typu T
, ale przykład przy cppreference pokazuje zarówno drugi, jak i trzeci parametr, które mają być tego samego typu. Sugeruje to, że przykład przy cppreference jest zepsuty. Próbowałem to naprawić, ale byłem zafascynowany potrzebą użycia reinterpret_cast
, która po prostu czuje się źle.
Co ciekawe, próbując to wymyślić, sprawdziłem numer msdn page for std::atomic_compare_exchange_weak
i byłem przerażony, widząc, że ta strona wyświetla prototypy dla std::atomic_compare_exchange_*strong*
!
Czy ktoś może opublikować wiarygodny kod, który używa std::atomic_compare_exchange_weak
do wstawienia węzła z przodu pojedynczo połączonej listy? Nie musisz martwić się o problem ABA ani robić nic nadzwyczajnego. Chciałbym po prostu zobaczyć kod, który się kompiluje.
Czy 'node' ma być obiektem atomowym? – 0x499602D2
To jest kompletny fragment kodu z cppreference, ale nie sądzę, że ma to wpływ na odpowiedź na moje pytanie. – KnowItAllWannabe
Kod jest nonsensem. Pierwszy argument do 'atomic_compare_exchange_weak' powinien być wskaźnikiem do obiektu typu atomowego; drugi argument powinien być wskaźnikiem do obiektu odpowiedniego typu wartości; trzeci argument jest obiektem (nie wskaźnikiem) odpowiedniego typu wartości. –