Код: Выделить всё
// Thread A:
// smart_ptr copy ctor
smart_ptr(const smart_ptr& other) {
...
control_block_ptr = other->control_block_ptr;
control_block_ptr->refs.fetch_add(1, memory_order_relaxed);
...
}
// Thread D:
// smart_ptr destructor
~smart_ptr() {
if (control_block_ptr->refs.fetch_sub(1, memory_order_acq_rel) == 1) {
delete control_block_ptr;
}
}
Увеличение эталонного счетчика всегда может быть сделано с помощью memory_order_relaxed: новые ссылки на объект могут быть сформированы только из существующей ссылки и передачи существующего ссылки из одного потока в другой Должен уже обеспечить любую необходимую синхронизацию.
Также я нашел ссылку https://gavinchou.github.io/summary/c++/memory-ondering /, где это написано: < /p>
Приращение может быть расслаблен (не операция публикации, никто не зависит от этого приращения). < /p>
Эти параграфы подразумевают, что эти приращения являются довольно независимыми, и здесь https://en.cppreference.com/w/cpp/atomic/memory_ord Независимые) Приращения. < /p>
Однако, в случае примера выше, приращения вообще не являются независимыми. Существует также одновременное сокращение, и они зависят от приращений (когда значение чтения составляет 1, объект удаляется). Приращения расслаблены, поэтому уменьшение может не увидеть их и удалить объект. Даже если мы рассмотрим, что операции RMW всегда читают последнее значение, порядок приращений/уменьшения, наблюдаемых в разных потоках Это не проблема, и не следует каким -то образом приращениям, как -то синхронизированным с уменьшением? Не могу понять два объяснения выше, к сожалению: они слишком короткие.
Подробнее здесь: https://stackoverflow.com/questions/793 ... d-with-dec