diff --git a/include/boost/smart_ptr/detail/sp_counted_base.hpp b/include/boost/smart_ptr/detail/sp_counted_base.hpp index f9a5c14..536926a 100644 --- a/include/boost/smart_ptr/detail/sp_counted_base.hpp +++ b/include/boost/smart_ptr/detail/sp_counted_base.hpp @@ -17,14 +17,9 @@ // http://www.boost.org/LICENSE_1_0.txt) // -#include +#include #include - -#if !defined( __c2__ ) && defined( __clang__ ) && defined( __has_extension ) -# if __has_extension( __c_atomic__ ) -# define BOOST_SP_HAS_CLANG_C11_ATOMICS -# endif -#endif +#include #if defined( BOOST_SP_DISABLE_THREADS ) # include @@ -41,18 +36,24 @@ #elif defined( BOOST_DISABLE_THREADS ) && !defined( BOOST_SP_ENABLE_THREADS ) && !defined( BOOST_DISABLE_WIN32 ) # include -#elif defined( BOOST_SP_HAS_CLANG_C11_ATOMICS ) -# include +#elif defined( BOOST_SP_HAS_GCC_INTRINSICS ) +# include #elif !defined( BOOST_NO_CXX11_HDR_ATOMIC ) # include -#elif defined( __SNC__ ) -# include +#elif defined( __GCC_HAVE_SYNC_COMPARE_AND_SWAP_4 ) +# include #elif defined( __GNUC__ ) && ( defined( __i386__ ) || defined( __x86_64__ ) ) && !defined(__PATHSCALE__) # include +#elif defined( BOOST_SP_HAS_SYNC_INTRINSICS ) +# include + +#elif defined( __SNC__ ) +# include + #elif defined(__HP_aCC) && defined(__ia64) # include @@ -71,9 +72,6 @@ #elif defined( __GNUC__ ) && ( defined( __mips__ ) || defined( _mips ) ) && !defined(__PATHSCALE__) && !defined( __mips16 ) # include -#elif defined( BOOST_SP_HAS_SYNC_INTRINSICS ) -# include - #elif defined(__GNUC__) && ( defined( __sparcv9 ) || ( defined( __sparcv8 ) && ( __GNUC__ * 100 + __GNUC_MINOR__ >= 402 ) ) ) # include @@ -91,6 +89,4 @@ #endif -#undef BOOST_SP_HAS_CLANG_C11_ATOMICS - #endif // #ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_HPP_INCLUDED diff --git a/include/boost/smart_ptr/detail/sp_counted_base_gcc_atomic.hpp b/include/boost/smart_ptr/detail/sp_counted_base_gcc_atomic.hpp new file mode 100644 index 0000000..c2172e9 --- /dev/null +++ b/include/boost/smart_ptr/detail/sp_counted_base_gcc_atomic.hpp @@ -0,0 +1,148 @@ +#ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_GCC_ATOMIC_HPP_INCLUDED +#define BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_GCC_ATOMIC_HPP_INCLUDED + +// MS compatible compilers support #pragma once + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +// detail/sp_counted_base_gc_atomic.hpp - g++ 4.7+ __atomic intrinsics +// +// Copyright 2007, 2020 Peter Dimov +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +#include +#include +#include + +#if defined(BOOST_SP_REPORT_IMPLEMENTATION) + +#include +BOOST_PRAGMA_MESSAGE("Using __atomic sp_counted_base") + +#endif + +namespace boost +{ + +namespace detail +{ + +inline void atomic_increment( boost::uint_least32_t * pw ) +{ + __atomic_fetch_add( pw, 1, __ATOMIC_RELAXED ); +} + +inline boost::uint_least32_t atomic_decrement( boost::uint_least32_t * pw ) +{ + return __atomic_fetch_sub( pw, 1, __ATOMIC_ACQ_REL ); +} + +inline boost::uint_least32_t atomic_conditional_increment( boost::uint_least32_t * pw ) +{ + // long r = *pw; + // if( r != 0 ) ++*pw; + // return r; + + boost::uint_least32_t r = __atomic_load_n( pw, __ATOMIC_RELAXED ); + + for( ;; ) + { + if( r == 0 ) + { + return r; + } + + if( __atomic_compare_exchange_n( pw, &r, r + 1, true, __ATOMIC_RELAXED, __ATOMIC_RELAXED ) ) + { + return r; + } + } +} + +inline boost::uint_least32_t atomic_load( boost::uint_least32_t const * pw ) +{ + return __atomic_load_n( pw, __ATOMIC_ACQUIRE ); +} + +class BOOST_SYMBOL_VISIBLE sp_counted_base +{ +private: + + sp_counted_base( sp_counted_base const & ); + sp_counted_base & operator= ( sp_counted_base const & ); + + boost::uint_least32_t use_count_; // #shared + boost::uint_least32_t weak_count_; // #weak + (#shared != 0) + +public: + + sp_counted_base(): use_count_( 1 ), weak_count_( 1 ) + { + } + + virtual ~sp_counted_base() // nothrow + { + } + + // dispose() is called when use_count_ drops to zero, to release + // the resources managed by *this. + + virtual void dispose() = 0; // nothrow + + // destroy() is called when weak_count_ drops to zero. + + virtual void destroy() // nothrow + { + delete this; + } + + virtual void * get_deleter( sp_typeinfo_ const & ti ) = 0; + virtual void * get_local_deleter( sp_typeinfo_ const & ti ) = 0; + virtual void * get_untyped_deleter() = 0; + + void add_ref_copy() + { + atomic_increment( &use_count_ ); + } + + bool add_ref_lock() // true on success + { + return atomic_conditional_increment( &use_count_ ) != 0; + } + + void release() // nothrow + { + if( atomic_decrement( &use_count_ ) == 1 ) + { + dispose(); + weak_release(); + } + } + + void weak_add_ref() // nothrow + { + atomic_increment( &weak_count_ ); + } + + void weak_release() // nothrow + { + if( atomic_decrement( &weak_count_ ) == 1 ) + { + destroy(); + } + } + + long use_count() const // nothrow + { + return atomic_load( &use_count_ ); + } +}; + +} // namespace detail + +} // namespace boost + +#endif // #ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_SYNC_HPP_INCLUDED diff --git a/include/boost/smart_ptr/detail/sp_has_gcc_intrinsics.hpp b/include/boost/smart_ptr/detail/sp_has_gcc_intrinsics.hpp new file mode 100644 index 0000000..2e15f79 --- /dev/null +++ b/include/boost/smart_ptr/detail/sp_has_gcc_intrinsics.hpp @@ -0,0 +1,27 @@ +#ifndef BOOST_SMART_PTR_DETAIL_SP_HAS_GCC_INTRINSICS_HPP_INCLUDED +#define BOOST_SMART_PTR_DETAIL_SP_HAS_GCC_INTRINSICS_HPP_INCLUDED + +// MS compatible compilers support #pragma once + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + + +// boost/smart_ptr/detail/sp_has_gcc_intrinsics.hpp +// +// Copyright 2020 Peter Dimov +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt +// +// Defines the BOOST_SP_HAS_GCC_INTRINSICS macro if the __atomic_* +// intrinsics are available. + + +#if defined( __ATOMIC_RELAXED ) && defined( __ATOMIC_ACQUIRE ) && defined( __ATOMIC_RELEASE ) && defined( __ATOMIC_ACQ_REL ) + +# define BOOST_SP_HAS_GCC_INTRINSICS + +#endif + +#endif // #ifndef BOOST_SMART_PTR_DETAIL_SP_HAS_GCC_INTRINSICS_HPP_INCLUDED