Ответ 1
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;
}
}
Вы хотите использовать atomic_thread_fence
, чтобы delete
был строго после fetch_sub
. Reference
Цитата из связанного текста:
Увеличение счетчика ссылок всегда можно выполнить с помощью memory_order_relaxed: новые ссылки на объект могут быть сформированы из существующей ссылки и передачи существующей ссылки из одного нить в другую уже должна обеспечивать любую необходимую синхронизацию.
Важно обеспечить любой возможный доступ к объекту в одном нить (через существующую ссылку), чтобы произойти до удаления объект в другом потоке. Это достигается путем "выпуска" после сброса ссылки (любой доступ к объекту через эта ссылка, очевидно, должна была произойти раньше), и "приобретать", перед удалением объекта.
Можно было бы использовать memory_order_acq_rel для fetch_sub но это приводит к ненужным операциям "приобретать", когда контрольный счетчик еще не достиг нулевого уровня и может налагать производительность штраф.