문제

In the boost::shared_ptr destructor, this is done:

if(--*pn == 0)
{
    boost::checked_delete(px);
    delete pn;
}

where pn is a pointer to the reference counter, which is typedefed as

shared_ptr::count_type -> detail::atomic_count -> long

I would have expected the long to be volatile long, given threaded usage and the non-atomic 0-check-and-deletion in the shared_ptr destructor above. Why isn't it volatile?

EDIT:

It turns out I looked at the header used when multi-threaded usage is not specified (atomic_count.hpp). In atomic_count_win32.hpp, the decrement is properly implemented for multithreaded usage.

도움이 되었습니까?

해결책

Because volatile is not necessary for multithreading, and does nothing beneficial, but potentially destroys a number of optimizations.

In order to ensure safe multithreaded access to a variable, the primitive we need is a memory barrier, which provides both the guarantee of volatile and a few others (it prevents memory access reordering across the barrier, which volatile doesn't do)

I believe shared_ptr uses atomic operations when possible, which implicitly provide a memory barrier. Otherwise it falls back to a mutex, which also provides a memory barrier.

See Why is volatile not considered useful in multithreaded C or C++ programming? or http://software.intel.com/en-us/blogs/2007/11/30/volatile-almost-useless-for-multi-threaded-programming/ for more details

Edit
count_type is not a long in the general case. It is convertible to a long. If you look in atomic_count.hpp, the typedef to long is only applied if no threading is available (in which case of course, no synchronization is necessary). Otherwise it uses the implementation defined in boost/smart_ptr/detail/atomic_count_pthreads.hpp or boost/smart_ptr/detail/atomic_count_win32.hpp or one of the other files listed. And those are synchronized wrapper classes that ensures all operations are done atomically.

다른 팁

volatile has virtually nothing to do with threading. See here.

You are misreading the code. atomic_count is defined simply as a long if the code is not using multithreading:

#ifndef BOOST_HAS_THREADS

namespace boost
{

namespace detail
{

typedef long atomic_count;

}

}

#elif //... include various platform-specific headers that define atomic_count class

#endif
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top