2013-04-16 18 views
7

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.

+1

Czy 'node' ma być obiektem atomowym? – 0x499602D2

+0

To jest kompletny fragment kodu z cppreference, ale nie sądzę, że ma to wpływ na odpowiedź na moje pytanie. – KnowItAllWannabe

+2

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. –

Odpowiedz

1

Prawidłowe Przykładem może być:

struct list { 
    std::atomic<node*> head; 
}; 

... 

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)); 
    // or while (!s->head.compare_exchange_weak(head, n)); 
} 

list::head musiałyby być std::atomic obiektu, chyba że chcesz do czynienia z nieokreślonym zachowanie. Platforma, o której mowa, może potrzebować niektórych lub wszystkich rzeczy, które będą implementowane za pomocą blokad. W związku z tym std::atomic<T*> może zawierać dodatkowych członków i reinterpret_cast<std::atomic<T*>*> byłby przypadek, w którym UB oznacza, że ​​twój program ulega awarii.

+0

Kompiluje to, gdy wokół niego zostanie zbudowany odpowiedni szkielet. [Przykład kompilacji] (http://ideone.com/eZnylZ) jest dostępny w IDEOne. Nie testowałem przykładowego kodu, aby upewnić się, że działa, ale przynajmniej się kompiluje. – KnowItAllWannabe

Powiązane problemy