Piszę uciążliwy udostępniony wskaźnik i używam obiektów C++ 11 <atomic>
dla licznika odwołań. Oto stosowne fragmenty mojego kodu:C++ 11 atomów i natarczywa dzielona liczba odnośników wskaźnik
//...
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;
}
zacząłem z memory_order_acquire
i memory_order_release
ale potem przekonałem się, że memory_order_consume
powinny być wystarczająco dobre. Po dalszych rozważaniach wydaje mi się, że powinien zadziałać nawet memory_order_relaxed
.
Teraz pytanie brzmi, czy mogę użyć memory_order_consume
do operacji lub czy mogę użyć słabszego zamawiania (memory_order_relaxed
), czy też powinienem zastosować bardziej rygorystyczne zamówienie?
Ponieważ licznik działa zasadniczo jako blokada rekursywna dla instrukcji 'delete', powiedziałbym, że" nabywanie "w' addReference' i "release" w 'removeReference' są poprawnymi porządkami. Ale twój 'addReference' powinien także upewnić się, że licznik nie jest równy zeru! –
@KerrekSB: Licznik może mieć wartość zero w 'addReference()' po utworzeniu obiektu przed przypisaniem go do 'SharedPtr <>. Selekcja/semantyka wydaje się, że powinna zawsze działać. Ale czy nie można użyć słabszego ograniczenia zleceń, a dlaczego nie? – wilx
O zera: załóżmy, że refcount wynosi 1. Teraz wątek 1 chce usunąć obiekt i wywołuje odejmowanie. Jeśli w tym momencie wątek 2 chce * zwiększyć * liczbę wątków, zwiększa się od zera do jednego, ale wątek 1 będzie kontynuowany i mimo to usunie obiekt. Tego należy unikać. –