2015-11-15 9 views
5

Sto scrivendo un costruttore di copia per una struttura dati che deve copiare due membri std::atomic<T> in un nuovo oggetto. Sebbene il processo non debba necessariamente essere atomico nel mio caso d'uso, preferirei avere la soluzione più corretta possibile.Modalità di blocco per la copia atomica nel Copy Manufacturer

Sono consapevole del fatto che il costruttore di copie viene eliminato esplicitamente con std::atomic<T> in modo da imporre agli utenti di utilizzare l'interfaccia atomica.

atomico (const atomico &) = elimina;

Quello che sto attualmente sto facendo qualcosa di simile:

SomeObject(const SomeObject& other): 
    _atomic1(other._atomic1.load()),    
    _atomic2(other._atomic2.load()) { 
... 
} 

Non credo che questa operazione è atomica, né so un modo per fare è così (senza serrature).

C'è un modo per copiare questi valori atomicamente (senza blocchi)?

+0

Non esiste un modo generale per copiare atomicamente due oggetti atomici casuali, se questo è ciò che si sta chiedendo. Aggiungi un mutex se hai effettivamente bisogno di una copia atomica. –

+3

9 volte su 10, la risposta a questa domanda sarà "non hai bisogno di farlo, stai andando su qualunque cosa tu stia facendo nel modo sbagliato". Se la struttura dei dati è una sorta di collezione, ad esempio, avrà già un modo per ottenere i suoi contenuti in un modo sicuro per la concorrenza, e dovresti usarlo. –

+0

@MattTimmermans Questo è un grande punto, anche se la mia domanda è di natura accademica. ** Gli spettatori di questa domanda dovrebbero prendere nota e utilizzare i tipi progettati dagli esperti, se possibile. ** La concorrenza è difficile, quindi se scrivi qualcosa da te, fallo revisionare. –

risposta

4

L'unico modo è di creare una struttura banalmente copiabile S contenente due T s e utilizzare std::atomic<S>.

Si noti che questo funziona solo se si sta usando questo S dall'inizio - non c'è modo di caricare atomicamente due atomici separati senza blocchi.

Così, invece di:

struct SomeObject { 
    SomeObject(const SomeObject& other) : i(other.i.load()), j(other.j.load()) { } 
    std::atomic<int> i, j; 
}; 

fare questo:

struct SomeObject { 
    SomeObject(const SomeObject& other) : data(other.data.load()) { } 
    struct Data { int i, j; }; 
    std::atomic<Data> data; 
}; 

Si noti che questo potrebbe (probabilmente) usa ancora serrature internamente. Utilizzare is_lock_free per verificare se lo fa.

+0

Hmm. È creativo, ma sospetto che usi le serrature internamente. Ci proverò. –

+0

@DonScott [Per le strutture <= 64 bit sembra essere senza blocco, ma non più grande.] (Http://coliru.stacked-crooked.com/a/e496ba55f9a710a8) – orlp

+0

Ho lo stesso risultato, ma gli spettatori dovrebbero notare che ** questo comportamento è dipendente dal compilatore e dall'architettura. ** I messaggi/scritture 8 byte allineati sono generalmente atomici su hardware recente (anche su sistemi operativi a 32 bit), ma gli utenti dovrebbero fare attenzione a verificare i loro sistemi. –

Problemi correlati