Estoy escribiendo puntero compartido intrusivo y estoy usando C++ 11 <atomic>
instalaciones para el contador de referencia. Estos son los fragmentos relevantes de mi código:C++ 11 atomics y cuenta de referencia de puntero compartido 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;
}
he empezado con memory_order_acquire
y memory_order_release
principio, pero luego me convencí de que memory_order_consume
debe ser lo suficientemente bueno. Después de una mayor deliberación, me parece que incluso memory_order_relaxed
debería funcionar.
Ahora, la pregunta es si puedo usar memory_order_consume
para las operaciones o podría usar un orden más débil (memory_order_relaxed
) o debería usar un orden más estricto?
Dado que el contador actúa esencialmente como un bloqueo recursivo para la declaración 'delete', diría que" acquire "en' addReference' y "release" en 'removeReference' son los pedidos correctos. ¡Pero su 'addReference' también debería asegurarse de que el contador no fuera cero! –
@KerrekSB: El contador puede ser cero en 'addReference()' después de crear el objeto por primera vez antes de asignarlo a 'SharedPtr <>'. La semántica de adquisición/liberación parece que siempre debería funcionar. ¿Pero no es posible usar una restricción de ordenamiento más débil y por qué no? – wilx
Acerca del cero: supongamos que el recuento es 1. Ahora el subproceso 1 quiere eliminar el objeto y resta las llamadas. Si en este punto el subproceso 2 desea * aumentar * el número de subprocesos, aumenta de cero a uno, pero el subproceso 1 continuará y eliminará el objeto de todos modos. Eso debe ser evitado. –