2012-12-13 20 views
5

Czy można bezpiecznie przenieść unique_ptr z operacjami atomowymi C++ 11?Bezpieczny wątek unique_ptr move

Obecnie mam kod jak ten

std::unique_ptr<SyncToken> DataManager::borrowSyncToken() 
{ 
    std::unique_lock<std::mutex> syncTokenLock(syncTokenMutex); 
    return std::move(syncToken); 
} 

Zastanawiam się, czy istnieje jakiś bardziej elegancki sposób, jak po prostu deklarując:

std::atomic<std::unique_ptr<SyncToken>> syncToken; 

i unikając potrzeby mutex. A może wcale nie muszę przejmować się zamkiem, a std :: move jest już atomowy?

Po badaniach zrobiłem do tej pory wydaje mi:

  • std :: poruszania się nie jest atomowa i musi mieć jakiś inny sposób synchronizacji około 2 nitki nazywając moją metodę jednocześnie może skończyć się 2 egzemplarzach niektórych niezdefiniowanych wskaźników.
  • Kompilacja std :: atomic kompiluje się dla mnie, ale nie wiem jak ją zainicjować i wykonać ruch.

Odpowiedz

2

Nie, nie jest to możliwe.

Wartość T które przechodzą do std::atomic musi być trywialnie copyable, który std::unique_ptr nie jest. Operacje takie jak std::atomic::load lub std::atomic::store pobierają obiekty T według wartości.

Pakowanie czegoś w std::atomic również nie powoduje operacji z wartości atomowej.

Podczas korzystania z std::unique_ptr w kontekście atomowym, musisz pomyśleć o tym, że możesz mieć problemy, jeśli chodzi o zarządzanie zasobami. Nigdy nie wiesz, ile wątków wciąż odwołuje się do twoich danych, ten problem można rozwiązać, używając std::shared_ptr, który używa liczenia odniesień atomowych. (Musisz sprawdzić, czy jest naprawdę atomowy, używając funkcji std::atomic_is_lock_free).

Jedną rzeczą, na którą natknąłem się również podczas szukania kodu, jest intencja funkcji borrowSyncToken. To się nazywa pożyczanie, ale przekazujesz własność tokena rozmówcy, przenosząc numer std::unique_ptr, w jaki sposób przekazuje się prawa własności i co zyskują inne wątki, gdy DataManager nie jest właścicielem tokena?

+0

Dzięki za odpowiedź i omówienie std :: shared_ptr. W tym celu: kod jest uproszczony, ale myślę, że mimo to zwróciłby nullptr do późniejszych wątków, pozwalając dzwoniącemu dowiedzieć się, że token nie jest dostępny. Problem rozwiązany tutaj wyjaśnię w innym komentarzu. –

+0

Klienci wykonują dwa typy operacji na DataManager: odczyt, zapis. Tylko jeden klient może pisać w tym czasie. ** Klienci nie są wątkami ** - czasami tak, czasami może być uruchomione zadanie tła dla klienta. czytanie/pisanie nie oznacza prostej operacji, ale po złożonym protokole komunikacyjnym między DataManager a klientem. Żądania klienta nie muszą być blokowane, dopóki nie zostanie udostępniony token, ale czasami będzie on aktywnie odrzucany. Aby zorientować się w bałaganie, zaproponowałem ten SyncToken - program piszący musi pożyczyć SyncToken i wywołać returnSyncToken (unique_ptr ) po zakończeniu. –

Powiązane problemy