significado ser pensamientos modo intrusivos intrusivo agresivos c++ c++11 shared-ptr atomic

ser - C++ 11 atómica y recuento de referencia de puntero compartido intrusivo



pensamientos intrusivos agresivos (1)

Estoy escribiendo un puntero compartido intrusivo y estoy usando C ++ 11 <atomic> facilidades para el contador de referencia. Aquí están los fragmentos relevantes de mi código:

//... 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; }

memory_order_acquire comencé con memory_order_acquire y memory_order_release pero luego me convencí de que memory_order_consume debería ser lo suficientemente bueno. Después de una deliberación adicional, me parece que incluso memory_order_relaxed debería funcionar.

Ahora, la pregunta es si puedo usar memory_order_consume para las operaciones o si puedo usar un ordenamiento más débil ( memory_order_relaxed ) o si debo usar un ordenamiento más estricto.


void SharedObject::addReference() const { std::atomic_fetch_add_explicit (&count, 1u, std::memory_order_relaxed); } void SharedObject::removeReference() const { if ( std::atomic_fetch_sub_explicit (&count, 1u, std::memory_order_release) == 1 ) { std::atomic_thread_fence(boost::memory_order_acquire); delete this; } }

Desea utilizar atomic_thread_fence modo que la delete sea ​​estrictamente después de fetch_sub . Reference

Cita del texto vinculado:

El aumento del contador de referencia siempre se puede hacer con memory_order_relaxed: las nuevas referencias a un objeto solo pueden formarse a partir de una referencia existente, y pasar una referencia existente de un hilo a otro ya debe proporcionar la sincronización necesaria.

Es importante imponer cualquier acceso posible al objeto en un hilo (a través de una referencia existente) para que ocurra antes de eliminar el objeto en un hilo diferente. Esto se logra mediante una operación de "liberación" después de eliminar una referencia (cualquier acceso al objeto a través de esta referencia obviamente debe haber ocurrido antes) y una operación de "adquisición" antes de eliminar el objeto.

Sería posible usar memory_order_acq_rel para la operación fetch_sub, pero esto resulta en operaciones de "adquisición" innecesarias cuando el contador de referencia aún no llega a cero y puede imponer una penalización de rendimiento.