В boost::shared_ptr
деструктор, это сделано:
if(--*pn == 0)
{
boost::checked_delete(px);
delete pn;
}
где pn
указатель на ссылочный счетчик, который является typedefed как
shared_ptr::count_type -> detail::atomic_count -> long
Я ожидал бы long
быть volatile long
, поданный распараллелил использование и неатомарный 0-check-and-deletion shared_ptr
деструктор выше. Почему это не энергозависимо?
Править:
Оказывается, что я посмотрел на заголовок, используемый, когда многопоточное использование не указано (atomic_count.hpp). В atomic_count_win32.hpp декремент правильно реализован для многопоточного использования.
Потому что volatile
не нужен для многопоточности, и не делает ничего полезного, но потенциально уничтожает ряд оптимизаций.
Чтобы обеспечить безопасный многопоточный доступ к переменной, нам нужен примитив - барьер памяти, который обеспечивает как гарантии volatile
, так и некоторые другие (он предотвращает переупорядочивание доступа к памяти через барьер, чего не делает volatile)
Я считаю, что shared_ptr
использует атомарные операции, когда это возможно, которые неявно обеспечивают барьер памяти. В противном случае он возвращается к мьютексу, который также обеспечивает барьер памяти.
См. Почему volatile не считается полезным в многопоточном программировании на C или C++? или http://software.intel.com/en-us/blogs/2007/11/30/volatile-almost-useless-for-multi-threaded-programming/ для более подробной информации
Редактировать
count_type
является не long
в общем случае. Он конвертируется в long
. Если вы посмотрите в atomic_count.hpp
, типизация к long применяется только в том случае, если нет потоковой обработки (в этом случае, конечно, синхронизация не нужна). В противном случае используется реализация, определенная в boost/smart_ptr/detail/atomic_count_pthreads.hpp
или boost/smart_ptr/detail/atomic_count_win32.hpp
или в одном из других перечисленных файлов. И это синхронизированные классы-обертки, которые гарантируют, что все операции выполняются атомарно.
volatile
практически не имеет ничего общего с потоками. См. здесь .
Вы неправильно читаете код. atomic_count
определяется просто как long, если код не использует многопоточность:
#ifndef BOOST_HAS_THREADS
namespace boost
{
namespace detail
{
typedef long atomic_count;
}
}
#elif //... include various platform-specific headers that define atomic_count class
#endif