diff --git a/include/boost/smart_ptr/detail/atomic_count.hpp b/include/boost/smart_ptr/detail/atomic_count.hpp index 6e4f71a..749b3f0 100644 --- a/include/boost/smart_ptr/detail/atomic_count.hpp +++ b/include/boost/smart_ptr/detail/atomic_count.hpp @@ -43,8 +43,9 @@ // Memory Ordering: acquire/release // +#include +#include #include -#include #if defined( BOOST_AC_DISABLE_THREADS ) # include @@ -73,15 +74,18 @@ #elif defined( BOOST_DISABLE_THREADS ) && !defined( BOOST_SP_ENABLE_THREADS ) && !defined( BOOST_DISABLE_WIN32 ) # include +#elif defined( BOOST_SP_HAS_GCC_INTRINSICS ) +# include + #elif !defined( BOOST_NO_CXX11_HDR_ATOMIC ) # include +#elif defined( BOOST_SP_HAS_SYNC_INTRINSICS ) +# include + #elif defined( __GNUC__ ) && ( defined( __i386__ ) || defined( __x86_64__ ) ) && !defined( __PATHSCALE__ ) # include -#elif defined( BOOST_SP_HAS_SYNC ) -# include - #elif defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__) # include diff --git a/include/boost/smart_ptr/detail/atomic_count_gcc_atomic.hpp b/include/boost/smart_ptr/detail/atomic_count_gcc_atomic.hpp new file mode 100644 index 0000000..801a7cb --- /dev/null +++ b/include/boost/smart_ptr/detail/atomic_count_gcc_atomic.hpp @@ -0,0 +1,63 @@ +#ifndef BOOST_SMART_PTR_DETAIL_ATOMIC_COUNT_GCC_ATOMIC_HPP_INCLUDED +#define BOOST_SMART_PTR_DETAIL_ATOMIC_COUNT_GCC_ATOMIC_HPP_INCLUDED + +// boost/detail/atomic_count_gcc_atomic.hpp +// +// atomic_count for g++ 4.7+ +// +// Copyright 2007, 2020 Peter Dimov +// +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +#include + +#if defined(BOOST_SP_REPORT_IMPLEMENTATION) + +#include +BOOST_PRAGMA_MESSAGE("Using __atomic atomic_count") + +#endif + +namespace boost +{ + +namespace detail +{ + +class atomic_count +{ +public: + + explicit atomic_count( long v ): value_( static_cast< boost::int_least32_t >( v ) ) + { + } + + long operator++() + { + return __atomic_add_fetch( &value_, +1, __ATOMIC_ACQ_REL ); + } + + long operator--() + { + return __atomic_add_fetch( &value_, -1, __ATOMIC_ACQ_REL ); + } + + operator long() const + { + return __atomic_load_n( &value_, __ATOMIC_ACQUIRE ); + } + +private: + + atomic_count(atomic_count const &); + atomic_count & operator=(atomic_count const &); + + boost::int_least32_t value_; +}; + +} // namespace detail + +} // namespace boost + +#endif // #ifndef BOOST_SMART_PTR_DETAIL_ATOMIC_COUNT_GCC_ATOMIC_HPP_INCLUDED diff --git a/include/boost/smart_ptr/detail/atomic_count_gcc_x86.hpp b/include/boost/smart_ptr/detail/atomic_count_gcc_x86.hpp index 100c9cf..30a73e3 100644 --- a/include/boost/smart_ptr/detail/atomic_count_gcc_x86.hpp +++ b/include/boost/smart_ptr/detail/atomic_count_gcc_x86.hpp @@ -13,6 +13,8 @@ // http://www.boost.org/LICENSE_1_0.txt) // +#include + #if defined(BOOST_SP_REPORT_IMPLEMENTATION) #include @@ -20,6 +22,8 @@ BOOST_PRAGMA_MESSAGE("Using g++/x86 atomic_count") #endif +BOOST_SP_OBSOLETE() + namespace boost { diff --git a/include/boost/smart_ptr/detail/atomic_count_solaris.hpp b/include/boost/smart_ptr/detail/atomic_count_solaris.hpp deleted file mode 100644 index fb80d0a..0000000 --- a/include/boost/smart_ptr/detail/atomic_count_solaris.hpp +++ /dev/null @@ -1,66 +0,0 @@ -#ifndef BOOST_SMART_PTR_DETAIL_ATOMIC_COUNT_SOLARIS_HPP_INCLUDED -#define BOOST_SMART_PTR_DETAIL_ATOMIC_COUNT_SOLARIS_HPP_INCLUDED - -// -// boost/detail/atomic_count_solaris.hpp -// based on: boost/detail/atomic_count_win32.hpp -// -// Copyright (c) 2001-2005 Peter Dimov -// Copyright (c) 2006 Michael van der Westhuizen -// -// Distributed under the Boost Software License, Version 1.0. (See -// accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// - -#include - -#if defined(BOOST_SP_REPORT_IMPLEMENTATION) - -#include -BOOST_PRAGMA_MESSAGE("Using Solaris atomic_count") - -#endif - -namespace boost -{ - -namespace detail -{ - -class atomic_count -{ -public: - - explicit atomic_count( uint32_t v ): value_( v ) - { - } - - long operator++() - { - return atomic_inc_32_nv( &value_ ); - } - - long operator--() - { - return atomic_dec_32_nv( &value_ ); - } - - operator uint32_t() const - { - return static_cast( value_ ); - } - -private: - - atomic_count( atomic_count const & ); - atomic_count & operator=( atomic_count const & ); - - uint32_t value_; -}; - -} // namespace detail - -} // namespace boost - -#endif // #ifndef BOOST_SMART_PTR_DETAIL_ATOMIC_COUNT_SOLARIS_HPP_INCLUDED diff --git a/include/boost/smart_ptr/detail/atomic_count_sync.hpp b/include/boost/smart_ptr/detail/atomic_count_sync.hpp index 81d7d65..65b42c8 100644 --- a/include/boost/smart_ptr/detail/atomic_count_sync.hpp +++ b/include/boost/smart_ptr/detail/atomic_count_sync.hpp @@ -15,6 +15,8 @@ // http://www.boost.org/LICENSE_1_0.txt) // +#include + #if defined( __ia64__ ) && defined( __INTEL_COMPILER ) # include #endif @@ -36,7 +38,9 @@ class atomic_count { public: - explicit atomic_count( long v ) : value_( v ) {} + explicit atomic_count( long v ): value_( static_cast< boost::int_least32_t >( v ) ) + { + } long operator++() { @@ -58,7 +62,7 @@ private: atomic_count(atomic_count const &); atomic_count & operator=(atomic_count const &); - mutable long value_; + mutable boost::int_least32_t value_; }; } // namespace detail diff --git a/include/boost/smart_ptr/detail/sp_counted_base.hpp b/include/boost/smart_ptr/detail/sp_counted_base.hpp index 4386137..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 -#include - -#if !defined( __c2__ ) && defined( __clang__ ) && defined( __has_extension ) -# if __has_extension( __c_atomic__ ) -# define BOOST_SP_HAS_CLANG_C11_ATOMICS -# endif -#endif #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 ) -# 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_acc_ia64.hpp b/include/boost/smart_ptr/detail/sp_counted_base_acc_ia64.hpp index b31997d..8482515 100644 --- a/include/boost/smart_ptr/detail/sp_counted_base_acc_ia64.hpp +++ b/include/boost/smart_ptr/detail/sp_counted_base_acc_ia64.hpp @@ -16,6 +16,7 @@ // #include +#include #include #include @@ -26,6 +27,8 @@ BOOST_PRAGMA_MESSAGE("Using HP aCC++/HP-UX/IA64 sp_counted_base") #endif +BOOST_SP_OBSOLETE() + namespace boost { diff --git a/include/boost/smart_ptr/detail/sp_counted_base_clang.hpp b/include/boost/smart_ptr/detail/sp_counted_base_clang.hpp deleted file mode 100644 index 3a2ab0e..0000000 --- a/include/boost/smart_ptr/detail/sp_counted_base_clang.hpp +++ /dev/null @@ -1,168 +0,0 @@ -#ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_CLANG_HPP_INCLUDED -#define BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_CLANG_HPP_INCLUDED - -// MS compatible compilers support #pragma once - -#if defined(_MSC_VER) && (_MSC_VER >= 1020) -# pragma once -#endif - -// detail/sp_counted_base_clang.hpp - __c11 clang intrinsics -// -// Copyright (c) 2007, 2013, 2015 Peter Dimov -// -// Distributed under the Boost Software License, Version 1.0. -// See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt - -#include -#include -#include -#include - -#if defined(BOOST_SP_REPORT_IMPLEMENTATION) - -#include -BOOST_PRAGMA_MESSAGE("Using Clang/C11 sp_counted_base") - -#endif - -namespace boost -{ - -namespace detail -{ - -#if defined(__clang__) -# pragma clang diagnostic push -#endif - -#if defined(__clang__) && defined(__has_warning) -# if __has_warning( "-Wc11-extensions" ) -# pragma clang diagnostic ignored "-Wc11-extensions" -# endif -#endif - -typedef _Atomic( boost::int_least32_t ) atomic_int_least32_t; - -inline void atomic_increment( atomic_int_least32_t * pw ) BOOST_SP_NOEXCEPT -{ - __c11_atomic_fetch_add( pw, 1, __ATOMIC_RELAXED ); -} - -inline boost::int_least32_t atomic_decrement( atomic_int_least32_t * pw ) BOOST_SP_NOEXCEPT -{ - return __c11_atomic_fetch_sub( pw, 1, __ATOMIC_ACQ_REL ); -} - -inline boost::int_least32_t atomic_conditional_increment( atomic_int_least32_t * pw ) BOOST_SP_NOEXCEPT -{ - // long r = *pw; - // if( r != 0 ) ++*pw; - // return r; - - boost::int_least32_t r = __c11_atomic_load( pw, __ATOMIC_RELAXED ); - - for( ;; ) - { - if( r == 0 ) - { - return r; - } - - if( __c11_atomic_compare_exchange_weak( pw, &r, r + 1, __ATOMIC_RELAXED, __ATOMIC_RELAXED ) ) - { - return r; - } - } -} - -#if defined(__clang__) -# pragma clang diagnostic ignored "-Wweak-vtables" -#endif - -class BOOST_SYMBOL_VISIBLE sp_counted_base -{ -private: - - sp_counted_base( sp_counted_base const & ); - sp_counted_base & operator= ( sp_counted_base const & ); - - atomic_int_least32_t use_count_; // #shared - atomic_int_least32_t weak_count_; // #weak + (#shared != 0) - -public: - - sp_counted_base() BOOST_SP_NOEXCEPT - { - __c11_atomic_init( &use_count_, 1 ); - __c11_atomic_init( &weak_count_, 1 ); - } - - virtual ~sp_counted_base() /*BOOST_SP_NOEXCEPT*/ - { - } - - // dispose() is called when use_count_ drops to zero, to release - // the resources managed by *this. - - virtual void dispose() BOOST_SP_NOEXCEPT = 0; // nothrow - - // destroy() is called when weak_count_ drops to zero. - - virtual void destroy() BOOST_SP_NOEXCEPT // nothrow - { - delete this; - } - - virtual void * get_deleter( sp_typeinfo_ const & ti ) BOOST_SP_NOEXCEPT = 0; - virtual void * get_local_deleter( sp_typeinfo_ const & ti ) BOOST_SP_NOEXCEPT = 0; - virtual void * get_untyped_deleter() BOOST_SP_NOEXCEPT = 0; - - void add_ref_copy() BOOST_SP_NOEXCEPT - { - atomic_increment( &use_count_ ); - } - - bool add_ref_lock() BOOST_SP_NOEXCEPT // true on success - { - return atomic_conditional_increment( &use_count_ ) != 0; - } - - void release() BOOST_SP_NOEXCEPT - { - if( atomic_decrement( &use_count_ ) == 1 ) - { - dispose(); - weak_release(); - } - } - - void weak_add_ref() BOOST_SP_NOEXCEPT - { - atomic_increment( &weak_count_ ); - } - - void weak_release() BOOST_SP_NOEXCEPT - { - if( atomic_decrement( &weak_count_ ) == 1 ) - { - destroy(); - } - } - - long use_count() const BOOST_SP_NOEXCEPT - { - return __c11_atomic_load( const_cast< atomic_int_least32_t* >( &use_count_ ), __ATOMIC_ACQUIRE ); - } -}; - -#if defined(__clang__) -# pragma clang diagnostic pop -#endif - -} // namespace detail - -} // namespace boost - -#endif // #ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_CLANG_HPP_INCLUDED diff --git a/include/boost/smart_ptr/detail/sp_counted_base_cw_ppc.hpp b/include/boost/smart_ptr/detail/sp_counted_base_cw_ppc.hpp index f9df68a..81387ce 100644 --- a/include/boost/smart_ptr/detail/sp_counted_base_cw_ppc.hpp +++ b/include/boost/smart_ptr/detail/sp_counted_base_cw_ppc.hpp @@ -25,6 +25,7 @@ // #include +#include #include #if defined(BOOST_SP_REPORT_IMPLEMENTATION) @@ -34,6 +35,8 @@ BOOST_PRAGMA_MESSAGE("Using CodeWarrior/PowerPC sp_counted_base") #endif +BOOST_SP_OBSOLETE() + namespace boost { diff --git a/include/boost/smart_ptr/detail/sp_counted_base_cw_x86.hpp b/include/boost/smart_ptr/detail/sp_counted_base_gcc_atomic.hpp similarity index 50% rename from include/boost/smart_ptr/detail/sp_counted_base_cw_x86.hpp rename to include/boost/smart_ptr/detail/sp_counted_base_gcc_atomic.hpp index 297f055..99ded0d 100644 --- a/include/boost/smart_ptr/detail/sp_counted_base_cw_x86.hpp +++ b/include/boost/smart_ptr/detail/sp_counted_base_gcc_atomic.hpp @@ -1,5 +1,5 @@ -#ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_CW_X86_HPP_INCLUDED -#define BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_CW_X86_HPP_INCLUDED +#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 @@ -7,31 +7,20 @@ # pragma once #endif +// detail/sp_counted_base_gcc_atomic.hpp - g++ 4.7+ __atomic intrinsics // -// detail/sp_counted_base_cw_x86.hpp - CodeWarrion on 486+ -// -// Copyright (c) 2001, 2002, 2003 Peter Dimov and Multi Media Ltd. -// Copyright 2004-2005 Peter Dimov -// Copyright 2005 Rene Rivera -// -// Distributed under the Boost Software License, Version 1.0. (See -// accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// -// Lock-free algorithm by Alexander Terekhov -// -// Thanks to Ben Hitchings for the #weak + (#shared != 0) -// formulation -// +// 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 CodeWarrior/x86 sp_counted_base") +BOOST_PRAGMA_MESSAGE("Using __atomic sp_counted_base") #endif @@ -41,50 +30,41 @@ namespace boost namespace detail { -inline int atomic_exchange_and_add( int * pw, int dv ) +inline void atomic_increment( boost::uint_least32_t * pw ) { - // int r = *pw; - // *pw += dv; + __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; - asm + boost::uint_least32_t r = __atomic_load_n( pw, __ATOMIC_RELAXED ); + + for( ;; ) { - mov esi, [pw] - mov eax, dv - lock xadd dword ptr [esi], eax + if( r == 0 ) + { + return r; + } + + if( __atomic_compare_exchange_n( pw, &r, r + 1, true, __ATOMIC_RELAXED, __ATOMIC_RELAXED ) ) + { + return r; + } } } -inline void atomic_increment( int * pw ) +inline boost::uint_least32_t atomic_load( boost::uint_least32_t const * pw ) { - //atomic_exchange_and_add( pw, 1 ); - - asm - { - mov esi, [pw] - lock inc dword ptr [esi] - } -} - -inline int atomic_conditional_increment( int * pw ) -{ - // int rv = *pw; - // if( rv != 0 ) ++*pw; - // return rv; - - asm - { - mov esi, [pw] - mov eax, dword ptr [esi] - L0: - test eax, eax - je L1 - mov ebx, eax - inc ebx - lock cmpxchg dword ptr [esi], ebx - jne L0 - L1: - } + return __atomic_load_n( pw, __ATOMIC_ACQUIRE ); } class BOOST_SYMBOL_VISIBLE sp_counted_base @@ -94,8 +74,8 @@ private: sp_counted_base( sp_counted_base const & ); sp_counted_base & operator= ( sp_counted_base const & ); - int use_count_; // #shared - int weak_count_; // #weak + (#shared != 0) + boost::uint_least32_t use_count_; // #shared + boost::uint_least32_t weak_count_; // #weak + (#shared != 0) public: @@ -135,7 +115,7 @@ public: void release() // nothrow { - if( atomic_exchange_and_add( &use_count_, -1 ) == 1 ) + if( atomic_decrement( &use_count_ ) == 1 ) { dispose(); weak_release(); @@ -149,7 +129,7 @@ public: void weak_release() // nothrow { - if( atomic_exchange_and_add( &weak_count_, -1 ) == 1 ) + if( atomic_decrement( &weak_count_ ) == 1 ) { destroy(); } @@ -157,7 +137,7 @@ public: long use_count() const // nothrow { - return static_cast( use_count_ ); + return atomic_load( &use_count_ ); } }; @@ -165,4 +145,4 @@ public: } // namespace boost -#endif // #ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_CW_X86_HPP_INCLUDED +#endif // #ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_SYNC_HPP_INCLUDED diff --git a/include/boost/smart_ptr/detail/sp_counted_base_gcc_ia64.hpp b/include/boost/smart_ptr/detail/sp_counted_base_gcc_ia64.hpp index 0c8d172..a6492ec 100644 --- a/include/boost/smart_ptr/detail/sp_counted_base_gcc_ia64.hpp +++ b/include/boost/smart_ptr/detail/sp_counted_base_gcc_ia64.hpp @@ -17,6 +17,7 @@ // #include +#include #include #if defined(BOOST_SP_REPORT_IMPLEMENTATION) @@ -26,6 +27,8 @@ BOOST_PRAGMA_MESSAGE("Using g++/IA64 sp_counted_base") #endif +BOOST_SP_OBSOLETE() + namespace boost { diff --git a/include/boost/smart_ptr/detail/sp_counted_base_gcc_mips.hpp b/include/boost/smart_ptr/detail/sp_counted_base_gcc_mips.hpp index 5cc5de9..3d3c7d3 100644 --- a/include/boost/smart_ptr/detail/sp_counted_base_gcc_mips.hpp +++ b/include/boost/smart_ptr/detail/sp_counted_base_gcc_mips.hpp @@ -21,6 +21,7 @@ // #include +#include #include #if defined(BOOST_SP_REPORT_IMPLEMENTATION) @@ -30,6 +31,8 @@ BOOST_PRAGMA_MESSAGE("Using g++/MIPS sp_counted_base") #endif +BOOST_SP_OBSOLETE() + namespace boost { diff --git a/include/boost/smart_ptr/detail/sp_counted_base_gcc_ppc.hpp b/include/boost/smart_ptr/detail/sp_counted_base_gcc_ppc.hpp index c5f84f5..12c8774 100644 --- a/include/boost/smart_ptr/detail/sp_counted_base_gcc_ppc.hpp +++ b/include/boost/smart_ptr/detail/sp_counted_base_gcc_ppc.hpp @@ -25,6 +25,7 @@ // #include +#include #include #if defined(BOOST_SP_REPORT_IMPLEMENTATION) @@ -34,6 +35,8 @@ BOOST_PRAGMA_MESSAGE("Using g++/PowerPC sp_counted_base") #endif +BOOST_SP_OBSOLETE() + namespace boost { diff --git a/include/boost/smart_ptr/detail/sp_counted_base_gcc_sparc.hpp b/include/boost/smart_ptr/detail/sp_counted_base_gcc_sparc.hpp index 8062487..a30e2a7 100644 --- a/include/boost/smart_ptr/detail/sp_counted_base_gcc_sparc.hpp +++ b/include/boost/smart_ptr/detail/sp_counted_base_gcc_sparc.hpp @@ -20,6 +20,7 @@ // Thanks to Michael van der Westhuizen #include +#include #include #include // int32_t @@ -30,6 +31,8 @@ BOOST_PRAGMA_MESSAGE("Using g++/Sparc sp_counted_base") #endif +BOOST_SP_OBSOLETE() + namespace boost { diff --git a/include/boost/smart_ptr/detail/sp_counted_base_gcc_x86.hpp b/include/boost/smart_ptr/detail/sp_counted_base_gcc_x86.hpp index 1c55918..420265d 100644 --- a/include/boost/smart_ptr/detail/sp_counted_base_gcc_x86.hpp +++ b/include/boost/smart_ptr/detail/sp_counted_base_gcc_x86.hpp @@ -25,6 +25,7 @@ // #include +#include #include #if defined(BOOST_SP_REPORT_IMPLEMENTATION) @@ -34,6 +35,8 @@ BOOST_PRAGMA_MESSAGE("Using g++/x86 sp_counted_base") #endif +BOOST_SP_OBSOLETE() + namespace boost { diff --git a/include/boost/smart_ptr/detail/sp_counted_base_snc_ps3.hpp b/include/boost/smart_ptr/detail/sp_counted_base_snc_ps3.hpp index d60dd75..fc84ec1 100644 --- a/include/boost/smart_ptr/detail/sp_counted_base_snc_ps3.hpp +++ b/include/boost/smart_ptr/detail/sp_counted_base_snc_ps3.hpp @@ -20,6 +20,7 @@ // Thanks to Michael van der Westhuizen #include +#include #include #include // uint32_t @@ -30,6 +31,8 @@ BOOST_PRAGMA_MESSAGE("Using PS3 sp_counted_base") #endif +BOOST_SP_OBSOLETE() + namespace boost { diff --git a/include/boost/smart_ptr/detail/sp_counted_base_solaris.hpp b/include/boost/smart_ptr/detail/sp_counted_base_solaris.hpp deleted file mode 100644 index 4ad6b5e..0000000 --- a/include/boost/smart_ptr/detail/sp_counted_base_solaris.hpp +++ /dev/null @@ -1,123 +0,0 @@ -#ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_SOLARIS_HPP_INCLUDED -#define BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_SOLARIS_HPP_INCLUDED - -// -// detail/sp_counted_base_solaris.hpp -// based on: detail/sp_counted_base_w32.hpp -// -// Copyright (c) 2001, 2002, 2003 Peter Dimov and Multi Media Ltd. -// Copyright 2004-2005 Peter Dimov -// Copyright 2006 Michael van der Westhuizen -// -// Distributed under the Boost Software License, Version 1.0. (See -// accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// -// Lock-free algorithm by Alexander Terekhov -// -// Thanks to Ben Hitchings for the #weak + (#shared != 0) -// formulation -// - -#include -#include -#include - -#if defined(BOOST_SP_REPORT_IMPLEMENTATION) - -#include -BOOST_PRAGMA_MESSAGE("Using Solaris sp_counted_base") - -#endif - -namespace boost -{ - -namespace detail -{ - -class BOOST_SYMBOL_VISIBLE sp_counted_base -{ -private: - - sp_counted_base( sp_counted_base const & ); - sp_counted_base & operator= ( sp_counted_base const & ); - - uint32_t use_count_; // #shared - uint32_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_inc_32( &use_count_ ); - } - - bool add_ref_lock() // true on success - { - for( ;; ) - { - uint32_t tmp = static_cast< uint32_t const volatile& >( use_count_ ); - if( tmp == 0 ) return false; - if( atomic_cas_32( &use_count_, tmp, tmp + 1 ) == tmp ) return true; - } - } - - void release() // nothrow - { - if( atomic_dec_32_nv( &use_count_ ) == 0 ) - { - dispose(); - weak_release(); - } - } - - void weak_add_ref() // nothrow - { - atomic_inc_32( &weak_count_ ); - } - - void weak_release() // nothrow - { - if( atomic_dec_32_nv( &weak_count_ ) == 0 ) - { - destroy(); - } - } - - long use_count() const // nothrow - { - return static_cast( use_count_ ); - } -}; - -} // namespace detail - -} // namespace boost - -#endif // #ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_SOLARIS_HPP_INCLUDED diff --git a/include/boost/smart_ptr/detail/sp_counted_base_vacpp_ppc.hpp b/include/boost/smart_ptr/detail/sp_counted_base_vacpp_ppc.hpp index e08536d..d3e5442 100644 --- a/include/boost/smart_ptr/detail/sp_counted_base_vacpp_ppc.hpp +++ b/include/boost/smart_ptr/detail/sp_counted_base_vacpp_ppc.hpp @@ -22,6 +22,7 @@ // #include +#include #include #if defined(BOOST_SP_REPORT_IMPLEMENTATION) @@ -31,6 +32,8 @@ BOOST_PRAGMA_MESSAGE("Using xlC/PowerPC sp_counted_base") #endif +BOOST_SP_OBSOLETE() + extern "builtin" void __lwsync(void); extern "builtin" void __isync(void); extern "builtin" int __fetch_and_add(volatile int* addr, int val); 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 diff --git a/include/boost/smart_ptr/detail/sp_has_sync.hpp b/include/boost/smart_ptr/detail/sp_has_sync.hpp deleted file mode 100644 index e1debf0..0000000 --- a/include/boost/smart_ptr/detail/sp_has_sync.hpp +++ /dev/null @@ -1,69 +0,0 @@ -#ifndef BOOST_SMART_PTR_DETAIL_SP_HAS_SYNC_HPP_INCLUDED -#define BOOST_SMART_PTR_DETAIL_SP_HAS_SYNC_HPP_INCLUDED - -// MS compatible compilers support #pragma once - -#if defined(_MSC_VER) && (_MSC_VER >= 1020) -# pragma once -#endif - -// -// boost/smart_ptr/detail/sp_has_sync.hpp -// -// Copyright (c) 2008, 2009 Peter Dimov -// -// Distributed under the Boost Software License, Version 1.0. -// See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// Defines the BOOST_SP_HAS_SYNC macro if the __sync_* intrinsics -// are available. -// - -#ifndef BOOST_SP_NO_SYNC - -#if !defined( __c2__ ) && defined( __GCC_HAVE_SYNC_COMPARE_AND_SWAP_4 ) - -# define BOOST_SP_HAS_SYNC - -#elif defined( __IBMCPP__ ) && ( __IBMCPP__ >= 1210 ) && !defined( __COMPILER_VER__ ) - -# define BOOST_SP_HAS_SYNC - -#elif !defined( __c2__ ) && defined( __GNUC__ ) && ( __GNUC__ * 100 + __GNUC_MINOR__ >= 401 ) - -#define BOOST_SP_HAS_SYNC - -#if defined( __arm__ ) || defined( __armel__ ) -#undef BOOST_SP_HAS_SYNC -#endif - -#if defined( __hppa ) || defined( __hppa__ ) -#undef BOOST_SP_HAS_SYNC -#endif - -#if defined( __m68k__ ) -#undef BOOST_SP_HAS_SYNC -#endif - -#if defined( __sh__ ) -#undef BOOST_SP_HAS_SYNC -#endif - -#if defined( __sparc__ ) -#undef BOOST_SP_HAS_SYNC -#endif - -#if defined( __INTEL_COMPILER ) && !defined( __ia64__ ) && ( __INTEL_COMPILER < 1110 ) -#undef BOOST_SP_HAS_SYNC -#endif - -#if defined(__PATHSCALE__) && ((__PATHCC__ == 4) && (__PATHCC_MINOR__ < 9)) -#undef BOOST_SP_HAS_SYNC -#endif - -#endif - -#endif // #ifndef BOOST_SP_NO_SYNC - -#endif // #ifndef BOOST_SMART_PTR_DETAIL_SP_HAS_SYNC_HPP_INCLUDED diff --git a/include/boost/smart_ptr/detail/sp_has_sync_intrinsics.hpp b/include/boost/smart_ptr/detail/sp_has_sync_intrinsics.hpp new file mode 100644 index 0000000..875d869 --- /dev/null +++ b/include/boost/smart_ptr/detail/sp_has_sync_intrinsics.hpp @@ -0,0 +1,69 @@ +#ifndef BOOST_SMART_PTR_DETAIL_SP_HAS_SYNC_INTRINSICS_HPP_INCLUDED +#define BOOST_SMART_PTR_DETAIL_SP_HAS_SYNC_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_sync_intrinsics.hpp +// +// Copyright (c) 2008, 2009 Peter Dimov +// +// Distributed under the Boost Software License, Version 1.0. +// See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +// Defines the BOOST_SP_HAS_SYNC_INTRINSICS macro if the __sync_* intrinsics +// are available. +// + +#if !defined( BOOST_SP_NO_SYNC_INTRINSICS ) && !defined( BOOST_SP_NO_SYNC ) + +#if defined( __GCC_HAVE_SYNC_COMPARE_AND_SWAP_4 ) && !defined( __c2__ ) + +# define BOOST_SP_HAS_SYNC_INTRINSICS + +#elif defined( __IBMCPP__ ) && ( __IBMCPP__ >= 1210 ) && !defined( __COMPILER_VER__ ) + +# define BOOST_SP_HAS_SYNC_INTRINSICS + +#elif defined( __GNUC__ ) && ( __GNUC__ * 100 + __GNUC_MINOR__ >= 401 ) && !defined( __c2__ ) + +#define BOOST_SP_HAS_SYNC_INTRINSICS + +#if defined( __arm__ ) || defined( __armel__ ) +#undef BOOST_SP_HAS_SYNC_INTRINSICS +#endif + +#if defined( __hppa ) || defined( __hppa__ ) +#undef BOOST_SP_HAS_SYNC_INTRINSICS +#endif + +#if defined( __m68k__ ) +#undef BOOST_SP_HAS_SYNC_INTRINSICS +#endif + +#if defined( __sh__ ) +#undef BOOST_SP_HAS_SYNC_INTRINSICS +#endif + +#if defined( __sparc__ ) +#undef BOOST_SP_HAS_SYNC_INTRINSICS +#endif + +#if defined( __INTEL_COMPILER ) && !defined( __ia64__ ) && ( __INTEL_COMPILER < 1110 ) +#undef BOOST_SP_HAS_SYNC_INTRINSICS +#endif + +#if defined(__PATHSCALE__) && ((__PATHCC__ == 4) && (__PATHCC_MINOR__ < 9)) +#undef BOOST_SP_HAS_SYNC_INTRINSICS +#endif + +#endif + +#endif // #if !defined( BOOST_SP_NO_SYNC_INTRINSICS ) && !defined( BOOST_SP_NO_SYNC ) + +#endif // #ifndef BOOST_SMART_PTR_DETAIL_SP_HAS_SYNC_INTRINSICS_HPP_INCLUDED diff --git a/include/boost/smart_ptr/detail/sp_obsolete.hpp b/include/boost/smart_ptr/detail/sp_obsolete.hpp new file mode 100644 index 0000000..021e72e --- /dev/null +++ b/include/boost/smart_ptr/detail/sp_obsolete.hpp @@ -0,0 +1,32 @@ +#ifndef BOOST_SMART_PTR_DETAIL_SP_OBSOLETE_HPP_INCLUDED +#define BOOST_SMART_PTR_DETAIL_SP_OBSOLETE_HPP_INCLUDED + +// MS compatible compilers support #pragma once + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + + +// boost/smart_ptr/detail/sp_obsolete.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_OBSOLETE macro that emits a deprecation +// message. + +#include + +#if !defined( BOOST_SP_NO_OBSOLETE_MESSAGE ) + +#define BOOST_SP_OBSOLETE() BOOST_PRAGMA_MESSAGE("This platform-specific implementation is presumed obsolete and is slated for removal. If you want it retained, please open an issue in https://github.com/boostorg/smart_ptr.") + +#else + +#define BOOST_SP_OBSOLETE() + +#endif + +#endif // #ifndef BOOST_SMART_PTR_DETAIL_SP_OBSOLETE_HPP_INCLUDED diff --git a/include/boost/smart_ptr/detail/sp_thread_pause.hpp b/include/boost/smart_ptr/detail/sp_thread_pause.hpp new file mode 100644 index 0000000..2cddd90 --- /dev/null +++ b/include/boost/smart_ptr/detail/sp_thread_pause.hpp @@ -0,0 +1,51 @@ +#ifndef BOOST_SMART_PTR_DETAIL_SP_THREAD_PAUSE_HPP_INCLUDED +#define BOOST_SMART_PTR_DETAIL_SP_THREAD_PAUSE_HPP_INCLUDED + +// MS compatible compilers support #pragma once + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +// boost/smart_ptr/detail/sp_thread_pause.hpp +// +// inline void bost::detail::sp_thread_pause(); +// +// Emits a "pause" instruction. +// +// Copyright 2008, 2020 Peter Dimov +// Distributed under the Boost Software License, Version 1.0 +// https://www.boost.org/LICENSE_1_0.txt + +#if defined(_MSC_VER) && _MSC_VER >= 1310 && ( defined(_M_IX86) || defined(_M_X64) ) && !defined(__c2__) + +extern "C" void _mm_pause(); + +#define BOOST_SP_PAUSE _mm_pause(); + +#elif defined(__GNUC__) && ( defined(__i386__) || defined(__x86_64__) ) + +#define BOOST_SP_PAUSE __asm__ __volatile__( "rep; nop" : : : "memory" ); + +#else + +#define BOOST_SP_PAUSE + +#endif + +namespace boost +{ +namespace detail +{ + +inline void sp_thread_pause() +{ + BOOST_SP_PAUSE +} + +} // namespace detail +} // namespace boost + +#undef BOOST_SP_PAUSE + +#endif // #ifndef BOOST_SMART_PTR_DETAIL_SP_THREAD_PAUSE_HPP_INCLUDED diff --git a/include/boost/smart_ptr/detail/sp_thread_sleep.hpp b/include/boost/smart_ptr/detail/sp_thread_sleep.hpp new file mode 100644 index 0000000..ff1d168 --- /dev/null +++ b/include/boost/smart_ptr/detail/sp_thread_sleep.hpp @@ -0,0 +1,104 @@ +#ifndef BOOST_SMART_PTR_DETAIL_SP_THREAD_SLEEP_HPP_INCLUDED +#define BOOST_SMART_PTR_DETAIL_SP_THREAD_SLEEP_HPP_INCLUDED + +// MS compatible compilers support #pragma once + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +// boost/smart_ptr/detail/sp_thread_sleep.hpp +// +// inline void bost::detail::sp_thread_sleep(); +// +// Cease execution for a while to yield to other threads, +// as if by calling nanosleep() with an appropriate interval. +// +// Copyright 2008, 2020 Peter Dimov +// Distributed under the Boost Software License, Version 1.0 +// https://www.boost.org/LICENSE_1_0.txt + +#include +#include + +#if defined( WIN32 ) || defined( _WIN32 ) || defined( __WIN32__ ) || defined( __CYGWIN__ ) + +#if defined(BOOST_SP_REPORT_IMPLEMENTATION) + BOOST_PRAGMA_MESSAGE("Using Sleep(1) in sp_thread_sleep") +#endif + +#include + +namespace boost +{ + +namespace detail +{ + +inline void sp_thread_sleep() +{ + Sleep( 1 ); +} + +} // namespace detail + +} // namespace boost + +#elif defined(BOOST_HAS_NANOSLEEP) + +#if defined(BOOST_SP_REPORT_IMPLEMENTATION) + BOOST_PRAGMA_MESSAGE("Using nanosleep() in sp_thread_sleep") +#endif + +#include + +namespace boost +{ + +namespace detail +{ + +inline void sp_thread_sleep() +{ + // g++ -Wextra warns on {} or {0} + struct timespec rqtp = { 0, 0 }; + + // POSIX says that timespec has tv_sec and tv_nsec + // But it doesn't guarantee order or placement + + rqtp.tv_sec = 0; + rqtp.tv_nsec = 1000; + + nanosleep( &rqtp, 0 ); +} + +} // namespace detail + +} // namespace boost + +#else + +#if defined(BOOST_SP_REPORT_IMPLEMENTATION) + BOOST_PRAGMA_MESSAGE("Using sp_thread_yield() in sp_thread_sleep") +#endif + +#include + +namespace boost +{ + +namespace detail +{ + +inline void sp_thread_sleep() +{ + sp_thread_yield(); +} + +} // namespace detail + +} // namespace boost + +#endif + +#endif // #ifndef BOOST_SMART_PTR_DETAIL_SP_THREAD_SLEEP_HPP_INCLUDED diff --git a/include/boost/smart_ptr/detail/sp_thread_yield.hpp b/include/boost/smart_ptr/detail/sp_thread_yield.hpp new file mode 100644 index 0000000..9a221cc --- /dev/null +++ b/include/boost/smart_ptr/detail/sp_thread_yield.hpp @@ -0,0 +1,100 @@ +#ifndef BOOST_SMART_PTR_DETAIL_SP_THREAD_YIELD_HPP_INCLUDED +#define BOOST_SMART_PTR_DETAIL_SP_THREAD_YIELD_HPP_INCLUDED + +// MS compatible compilers support #pragma once + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +// boost/smart_ptr/detail/sp_thread_yield.hpp +// +// inline void bost::detail::sp_thread_yield(); +// +// Gives up the remainder of the time slice, +// as if by calling sched_yield(). +// +// Copyright 2008, 2020 Peter Dimov +// Distributed under the Boost Software License, Version 1.0 +// https://www.boost.org/LICENSE_1_0.txt + +#include +#include + +#if defined( WIN32 ) || defined( _WIN32 ) || defined( __WIN32__ ) || defined( __CYGWIN__ ) + +#if defined(BOOST_SP_REPORT_IMPLEMENTATION) + BOOST_PRAGMA_MESSAGE("Using Sleep(0) in sp_thread_yield") +#endif + +#include + +namespace boost +{ + +namespace detail +{ + +inline void sp_thread_yield() +{ + Sleep( 0 ); +} + +} // namespace detail + +} // namespace boost + +#elif defined(BOOST_HAS_SCHED_YIELD) + +#if defined(BOOST_SP_REPORT_IMPLEMENTATION) + BOOST_PRAGMA_MESSAGE("Using sched_yield() in sp_thread_yield") +#endif + +#ifndef _AIX +# include +#else + // AIX's sched.h defines ::var which sometimes conflicts with Lambda's var + extern "C" int sched_yield(void); +#endif + +namespace boost +{ + +namespace detail +{ + +inline void sp_thread_yield() +{ + sched_yield(); +} + +} // namespace detail + +} // namespace boost + +#else + +#if defined(BOOST_SP_REPORT_IMPLEMENTATION) + BOOST_PRAGMA_MESSAGE("Using sp_thread_pause() in sp_thread_yield") +#endif + +#include + +namespace boost +{ + +namespace detail +{ + +inline void sp_thread_yield() +{ + sp_thread_pause(); +} + +} // namespace detail + +} // namespace boost + +#endif + +#endif // #ifndef BOOST_SMART_PTR_DETAIL_SP_THREAD_YIELD_HPP_INCLUDED diff --git a/include/boost/smart_ptr/detail/sp_win32_sleep.hpp b/include/boost/smart_ptr/detail/sp_win32_sleep.hpp new file mode 100644 index 0000000..139a569 --- /dev/null +++ b/include/boost/smart_ptr/detail/sp_win32_sleep.hpp @@ -0,0 +1,49 @@ +#ifndef BOOST_SMART_PTR_DETAIL_SP_WIN32_SLEEP_HPP_INCLUDED +#define BOOST_SMART_PTR_DETAIL_SP_WIN32_SLEEP_HPP_INCLUDED + +// MS compatible compilers support #pragma once + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +// boost/smart_ptr/detail/sp_win32_sleep.hpp +// +// Declares the Win32 Sleep() function. +// +// Copyright 2008, 2020 Peter Dimov +// Distributed under the Boost Software License, Version 1.0 +// https://www.boost.org/LICENSE_1_0.txt + +#if defined( BOOST_USE_WINDOWS_H ) +# include +#endif + +namespace boost +{ +namespace detail +{ + +#if !defined( BOOST_USE_WINDOWS_H ) + +#if defined(__clang__) && defined(__x86_64__) +// clang x64 warns that __stdcall is ignored +# define BOOST_SP_STDCALL +#else +# define BOOST_SP_STDCALL __stdcall +#endif + +#if defined(__LP64__) // Cygwin 64 + extern "C" __declspec(dllimport) void BOOST_SP_STDCALL Sleep( unsigned int ms ); +#else + extern "C" __declspec(dllimport) void BOOST_SP_STDCALL Sleep( unsigned long ms ); +#endif + +#undef BOOST_SP_STDCALL + +#endif // !defined( BOOST_USE_WINDOWS_H ) + +} // namespace detail +} // namespace boost + +#endif // #ifndef BOOST_SMART_PTR_DETAIL_SP_WIN32_SLEEP_HPP_INCLUDED diff --git a/include/boost/smart_ptr/detail/spinlock.hpp b/include/boost/smart_ptr/detail/spinlock.hpp index 0b618df..26e1b08 100644 --- a/include/boost/smart_ptr/detail/spinlock.hpp +++ b/include/boost/smart_ptr/detail/spinlock.hpp @@ -28,28 +28,26 @@ // #define BOOST_DETAIL_SPINLOCK_INIT // +#include +#include #include -#include #if defined( BOOST_SP_USE_STD_ATOMIC ) -# if !defined( __clang__ ) -# include -# else -// Clang (at least up to 3.4) can't compile spinlock_pool when -// using std::atomic, so substitute the __sync implementation instead. -# include -# endif +# include #elif defined( BOOST_SP_USE_PTHREADS ) # include +#elif defined( BOOST_SP_HAS_GCC_INTRINSICS ) +# include + #elif !defined( BOOST_NO_CXX11_HDR_ATOMIC ) # include #elif defined(__GNUC__) && defined( __arm__ ) && !defined( __thumb__ ) # include -#elif defined( BOOST_SP_HAS_SYNC ) +#elif defined( BOOST_SP_HAS_SYNC_INTRINSICS ) # include #elif defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__) diff --git a/include/boost/smart_ptr/detail/spinlock_gcc_atomic.hpp b/include/boost/smart_ptr/detail/spinlock_gcc_atomic.hpp new file mode 100644 index 0000000..8cd7179 --- /dev/null +++ b/include/boost/smart_ptr/detail/spinlock_gcc_atomic.hpp @@ -0,0 +1,85 @@ +#ifndef BOOST_SMART_PTR_DETAIL_SPINLOCK_GCC_ATOMIC_HPP_INCLUDED +#define BOOST_SMART_PTR_DETAIL_SPINLOCK_GCC_ATOMIC_HPP_INCLUDED + +// MS compatible compilers support #pragma once + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +// Copyright 2008, 2020 Peter Dimov +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +#include + +#if defined(BOOST_SP_REPORT_IMPLEMENTATION) + +#include +BOOST_PRAGMA_MESSAGE("Using __atomic spinlock") + +#endif + +namespace boost +{ + +namespace detail +{ + +class spinlock +{ +public: + + unsigned char v_; + +public: + + bool try_lock() + { + return __atomic_test_and_set( &v_, __ATOMIC_ACQUIRE ) == 0; + } + + void lock() + { + for( unsigned k = 0; !try_lock(); ++k ) + { + boost::detail::yield( k ); + } + } + + void unlock() + { + __atomic_clear( &v_, __ATOMIC_RELEASE ); + } + +public: + + class scoped_lock + { + private: + + spinlock & sp_; + + scoped_lock( scoped_lock const & ); + scoped_lock & operator=( scoped_lock const & ); + + public: + + explicit scoped_lock( spinlock & sp ): sp_( sp ) + { + sp.lock(); + } + + ~scoped_lock() + { + sp_.unlock(); + } + }; +}; + +} // namespace detail +} // namespace boost + +#define BOOST_DETAIL_SPINLOCK_INIT {0} + +#endif // #ifndef BOOST_SMART_PTR_DETAIL_SPINLOCK_GCC_ATOMIC_HPP_INCLUDED diff --git a/include/boost/smart_ptr/detail/spinlock_sync.hpp b/include/boost/smart_ptr/detail/spinlock_sync.hpp index 854cc7e..cbfdd94 100644 --- a/include/boost/smart_ptr/detail/spinlock_sync.hpp +++ b/include/boost/smart_ptr/detail/spinlock_sync.hpp @@ -38,7 +38,7 @@ class spinlock { public: - int v_; + unsigned char v_; public: diff --git a/include/boost/smart_ptr/detail/yield_k.hpp b/include/boost/smart_ptr/detail/yield_k.hpp index fa25917..d9a1b46 100644 --- a/include/boost/smart_ptr/detail/yield_k.hpp +++ b/include/boost/smart_ptr/detail/yield_k.hpp @@ -7,107 +7,22 @@ # pragma once #endif +// boost/smart_ptr/detail/yield_k.hpp // -// yield_k.hpp +// Copyright 2008, 2020 Peter Dimov // -// Copyright (c) 2008 Peter Dimov +// inline void boost::detail::yield( unsigned k ); // -// void yield( unsigned k ); -// -// Typical use: -// -// for( unsigned k = 0; !try_lock(); ++k ) yield( k ); -// -// Distributed under the Boost Software License, Version 1.0. -// See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt +// Typical use: +// for( unsigned k = 0; !try_lock(); ++k ) yield( k ); // +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt +#include +#include #include -// BOOST_SMT_PAUSE - -#if defined(_MSC_VER) && _MSC_VER >= 1310 && ( defined(_M_IX86) || defined(_M_X64) ) && !defined(__c2__) - -extern "C" void _mm_pause(); - -#define BOOST_SMT_PAUSE _mm_pause(); - -#elif defined(__GNUC__) && ( defined(__i386__) || defined(__x86_64__) ) - -#define BOOST_SMT_PAUSE __asm__ __volatile__( "rep; nop" : : : "memory" ); - -#endif - -// - -#if defined( WIN32 ) || defined( _WIN32 ) || defined( __WIN32__ ) || defined( __CYGWIN__ ) - -#if defined( BOOST_USE_WINDOWS_H ) -# include -#endif - -namespace boost -{ - -namespace detail -{ - -#if !defined( BOOST_USE_WINDOWS_H ) - -#if defined(__clang__) && defined(__x86_64__) -// clang x64 warns that __stdcall is ignored -# define BOOST_SP_STDCALL -#else -# define BOOST_SP_STDCALL __stdcall -#endif - -#if defined(__LP64__) // Cygwin 64 - extern "C" __declspec(dllimport) void BOOST_SP_STDCALL Sleep( unsigned int ms ); -#else - extern "C" __declspec(dllimport) void BOOST_SP_STDCALL Sleep( unsigned long ms ); -#endif - -#undef BOOST_SP_STDCALL - -#endif // !defined( BOOST_USE_WINDOWS_H ) - -inline void yield( unsigned k ) BOOST_NOEXCEPT -{ - if( k < 4 ) - { - } -#if defined( BOOST_SMT_PAUSE ) - else if( k < 16 ) - { - BOOST_SMT_PAUSE - } -#endif - else if( k < 32 ) - { - Sleep( 0 ); - } - else - { - Sleep( 1 ); - } -} - -} // namespace detail - -} // namespace boost - -#elif defined( BOOST_HAS_PTHREADS ) - -#ifndef _AIX -#include -#else - // AIX's sched.h defines ::var which sometimes conflicts with Lambda's var - extern "C" int sched_yield(void); -#endif - -#include - namespace boost { @@ -116,31 +31,16 @@ namespace detail inline void yield( unsigned k ) { - if( k < 4 ) + // Experiments on Windows and Fedora 32 show that a single pause, + // followed by an immediate sp_thread_sleep(), is best. + + if( k == 0 ) { - } -#if defined( BOOST_SMT_PAUSE ) - else if( k < 16 ) - { - BOOST_SMT_PAUSE - } -#endif - else if( k < 32 || k & 1 ) - { - sched_yield(); + sp_thread_pause(); } else { - // g++ -Wextra warns on {} or {0} - struct timespec rqtp = { 0, 0 }; - - // POSIX says that timespec has tv_sec and tv_nsec - // But it doesn't guarantee order or placement - - rqtp.tv_sec = 0; - rqtp.tv_nsec = 1000; - - nanosleep( &rqtp, 0 ); + sp_thread_sleep(); } } @@ -148,22 +48,4 @@ inline void yield( unsigned k ) } // namespace boost -#else - -namespace boost -{ - -namespace detail -{ - -inline void yield( unsigned ) -{ -} - -} // namespace detail - -} // namespace boost - -#endif - #endif // #ifndef BOOST_SMART_PTR_DETAIL_YIELD_K_HPP_INCLUDED