Sto scrivendo un puntatore condiviso intrusivo e sto utilizzando le strutture C++ 11 <atomic>
per il contatore di riferimento. Qui ci sono i frammenti pertinenti del mio codice:C++ 11 atomica e conteggio di riferimento del puntatore condiviso intrusivo
//...
mutable std::atomic<unsigned> count;
//...
void
SharedObject::addReference() const
{
std::atomic_fetch_add_explicit (&count, 1u,
std::memory_order_consume);
}
void
SharedObject::removeReference() const
{
bool destroy;
destroy = std::atomic_fetch_sub_explicit (&count, 1u,
std::memory_order_consume) == 1;
if (destroy)
delete this;
}
ho iniziato con memory_order_acquire
e memory_order_release
primo momento, ma poi mi sono convinto che memory_order_consume
dovrebbe essere abbastanza buono. Dopo un'ulteriore riflessione, mi sembra che anche memory_order_relaxed
dovrebbe funzionare.
Ora, la domanda è se io possa usare memory_order_consume
per le operazioni o potrei usare un ordine più debole (memory_order_relaxed
) o dovrei usare un ordine più severo?
Poiché il contatore agisce essenzialmente come un blocco ricorsivo per l'istruzione 'delete', direi che" acquisisci "in" addReference "e" release "in" removeReference "sono gli ordinamenti giusti. Ma il tuo 'addReference' dovrebbe anche assicurarsi che il contatore non fosse zero! –
@KerrekSB: il contatore può essere zero in 'addReference()' dopo che l'oggetto è stato creato prima di essere assegnato a 'SharedPtr <>'. Acquisire/rilasciare semantica sembra che dovrebbe sempre funzionare. Ma non è possibile utilizzare un vincolo di ordine più debole e perché no? – wilx
Informazioni sullo zero: Supponiamo che il Refcount sia 1. Ora il thread 1 vuole eliminare l'oggetto e le chiamate sottrarre. Se a questo punto il thread 2 vuole * aumentare * il numero di thread, incrementa zero a uno, ma il thread 1 andrà avanti e cancellerà comunque l'oggetto. Questo dovrebbe essere evitato. –