From 906c207cca2da2714252d77f9098c51f239ea8bb Mon Sep 17 00:00:00 2001 From: Yuri Kunde Schlesner Date: Mon, 29 Dec 2014 19:38:48 -0200 Subject: [PATCH] Add smart_ptr/intrusive_ptr --- Readme.md | 1 + boost/smart_ptr/detail/operator_bool.hpp | 63 ++++ boost/smart_ptr/detail/sp_convertible.hpp | 91 ++++++ boost/smart_ptr/detail/sp_nullptr_t.hpp | 45 +++ boost/smart_ptr/intrusive_ptr.hpp | 336 ++++++++++++++++++++++ 5 files changed, 536 insertions(+) create mode 100644 boost/smart_ptr/detail/operator_bool.hpp create mode 100644 boost/smart_ptr/detail/sp_convertible.hpp create mode 100644 boost/smart_ptr/detail/sp_nullptr_t.hpp create mode 100644 boost/smart_ptr/intrusive_ptr.hpp diff --git a/Readme.md b/Readme.md index 2626956..83dea93 100644 --- a/Readme.md +++ b/Readme.md @@ -10,6 +10,7 @@ Currently imported libraries: * mpl * preprocessor * range +* smart_ptr (`intrusive_ptr` only) * type_traits * utility diff --git a/boost/smart_ptr/detail/operator_bool.hpp b/boost/smart_ptr/detail/operator_bool.hpp new file mode 100644 index 0000000..8ae1527 --- /dev/null +++ b/boost/smart_ptr/detail/operator_bool.hpp @@ -0,0 +1,63 @@ +// This header intentionally has no include guards. +// +// Copyright (c) 2001-2009, 2012 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 + +#if !defined( BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS ) && !defined( BOOST_NO_CXX11_NULLPTR ) + + explicit operator bool () const BOOST_NOEXCEPT + { + return px != 0; + } + +#elif ( defined(__SUNPRO_CC) && BOOST_WORKAROUND(__SUNPRO_CC, < 0x570) ) || defined(__CINT__) + + operator bool () const BOOST_NOEXCEPT + { + return px != 0; + } + +#elif defined( _MANAGED ) + + static void unspecified_bool( this_type*** ) + { + } + + typedef void (*unspecified_bool_type)( this_type*** ); + + operator unspecified_bool_type() const BOOST_NOEXCEPT + { + return px == 0? 0: unspecified_bool; + } + +#elif \ + ( defined(__MWERKS__) && BOOST_WORKAROUND(__MWERKS__, < 0x3200) ) || \ + ( defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ < 304) ) || \ + ( defined(__SUNPRO_CC) && BOOST_WORKAROUND(__SUNPRO_CC, <= 0x590) ) + + typedef element_type * (this_type::*unspecified_bool_type)() const; + + operator unspecified_bool_type() const BOOST_NOEXCEPT + { + return px == 0? 0: &this_type::get; + } + +#else + + typedef element_type * this_type::*unspecified_bool_type; + + operator unspecified_bool_type() const BOOST_NOEXCEPT + { + return px == 0? 0: &this_type::px; + } + +#endif + + // operator! is redundant, but some compilers need it + bool operator! () const BOOST_NOEXCEPT + { + return px == 0; + } diff --git a/boost/smart_ptr/detail/sp_convertible.hpp b/boost/smart_ptr/detail/sp_convertible.hpp new file mode 100644 index 0000000..31b2627 --- /dev/null +++ b/boost/smart_ptr/detail/sp_convertible.hpp @@ -0,0 +1,91 @@ +#ifndef BOOST_SMART_PTR_DETAIL_SP_CONVERTIBLE_HPP_INCLUDED +#define BOOST_SMART_PTR_DETAIL_SP_CONVERTIBLE_HPP_INCLUDED + +// MS compatible compilers support #pragma once + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +// detail/sp_convertible.hpp +// +// Copyright 2008 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 + +#if !defined( BOOST_SP_NO_SP_CONVERTIBLE ) && defined( BOOST_NO_SFINAE ) +# define BOOST_SP_NO_SP_CONVERTIBLE +#endif + +#if !defined( BOOST_SP_NO_SP_CONVERTIBLE ) && defined( __GNUC__ ) && ( __GNUC__ * 100 + __GNUC_MINOR__ < 303 ) +# define BOOST_SP_NO_SP_CONVERTIBLE +#endif + +#if !defined( BOOST_SP_NO_SP_CONVERTIBLE ) && defined( __BORLANDC__ ) && ( __BORLANDC__ < 0x630 ) +# define BOOST_SP_NO_SP_CONVERTIBLE +#endif + +#if !defined( BOOST_SP_NO_SP_CONVERTIBLE ) + +namespace boost +{ + +namespace detail +{ + +template< class Y, class T > struct sp_convertible +{ + typedef char (&yes) [1]; + typedef char (&no) [2]; + + static yes f( T* ); + static no f( ... ); + + enum _vt { value = sizeof( (f)( static_cast(0) ) ) == sizeof(yes) }; +}; + +template< class Y, class T > struct sp_convertible< Y, T[] > +{ + enum _vt { value = false }; +}; + +template< class Y, class T > struct sp_convertible< Y[], T[] > +{ + enum _vt { value = sp_convertible< Y[1], T[1] >::value }; +}; + +template< class Y, std::size_t N, class T > struct sp_convertible< Y[N], T[] > +{ + enum _vt { value = sp_convertible< Y[1], T[1] >::value }; +}; + +struct sp_empty +{ +}; + +template< bool > struct sp_enable_if_convertible_impl; + +template<> struct sp_enable_if_convertible_impl +{ + typedef sp_empty type; +}; + +template<> struct sp_enable_if_convertible_impl +{ +}; + +template< class Y, class T > struct sp_enable_if_convertible: public sp_enable_if_convertible_impl< sp_convertible< Y, T >::value > +{ +}; + +} // namespace detail + +} // namespace boost + +#endif // !defined( BOOST_SP_NO_SP_CONVERTIBLE ) + +#endif // #ifndef BOOST_SMART_PTR_DETAIL_SP_CONVERTIBLE_HPP_INCLUDED diff --git a/boost/smart_ptr/detail/sp_nullptr_t.hpp b/boost/smart_ptr/detail/sp_nullptr_t.hpp new file mode 100644 index 0000000..219ae80 --- /dev/null +++ b/boost/smart_ptr/detail/sp_nullptr_t.hpp @@ -0,0 +1,45 @@ +#ifndef BOOST_SMART_PTR_DETAIL_SP_NULLPTR_T_HPP_INCLUDED +#define BOOST_SMART_PTR_DETAIL_SP_NULLPTR_T_HPP_INCLUDED + +// MS compatible compilers support #pragma once + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +// detail/sp_nullptr_t.hpp +// +// Copyright 2013 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 + +#if !defined( BOOST_NO_CXX11_NULLPTR ) + +namespace boost +{ + +namespace detail +{ + +#if !defined( BOOST_NO_CXX11_DECLTYPE ) && ( ( defined( __clang__ ) && !defined( _LIBCPP_VERSION ) ) || defined( __INTEL_COMPILER ) ) + + typedef decltype(nullptr) sp_nullptr_t; + +#else + + typedef std::nullptr_t sp_nullptr_t; + +#endif + +} // namespace detail + +} // namespace boost + +#endif // !defined( BOOST_NO_CXX11_NULLPTR ) + +#endif // #ifndef BOOST_SMART_PTR_DETAIL_SP_NULLPTR_T_HPP_INCLUDED diff --git a/boost/smart_ptr/intrusive_ptr.hpp b/boost/smart_ptr/intrusive_ptr.hpp new file mode 100644 index 0000000..e5db609 --- /dev/null +++ b/boost/smart_ptr/intrusive_ptr.hpp @@ -0,0 +1,336 @@ +#ifndef BOOST_SMART_PTR_INTRUSIVE_PTR_HPP_INCLUDED +#define BOOST_SMART_PTR_INTRUSIVE_PTR_HPP_INCLUDED + +// +// intrusive_ptr.hpp +// +// Copyright (c) 2001, 2002 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) +// +// See http://www.boost.org/libs/smart_ptr/intrusive_ptr.html for documentation. +// + +#include + +#include +#include +#include +#include + +#include // for std::less + +#if !defined(BOOST_NO_IOSTREAM) +#if !defined(BOOST_NO_IOSFWD) +#include // for std::basic_ostream +#else +#include +#endif +#endif + + +namespace boost +{ + +// +// intrusive_ptr +// +// A smart pointer that uses intrusive reference counting. +// +// Relies on unqualified calls to +// +// void intrusive_ptr_add_ref(T * p); +// void intrusive_ptr_release(T * p); +// +// (p != 0) +// +// The object is responsible for destroying itself. +// + +template class intrusive_ptr +{ +private: + + typedef intrusive_ptr this_type; + +public: + + typedef T element_type; + + intrusive_ptr() BOOST_NOEXCEPT : px( 0 ) + { + } + + intrusive_ptr( T * p, bool add_ref = true ): px( p ) + { + if( px != 0 && add_ref ) intrusive_ptr_add_ref( px ); + } + +#if !defined(BOOST_NO_MEMBER_TEMPLATES) || defined(BOOST_MSVC6_MEMBER_TEMPLATES) + + template +#if !defined( BOOST_SP_NO_SP_CONVERTIBLE ) + + intrusive_ptr( intrusive_ptr const & rhs, typename boost::detail::sp_enable_if_convertible::type = boost::detail::sp_empty() ) + +#else + + intrusive_ptr( intrusive_ptr const & rhs ) + +#endif + : px( rhs.get() ) + { + if( px != 0 ) intrusive_ptr_add_ref( px ); + } + +#endif + + intrusive_ptr(intrusive_ptr const & rhs): px( rhs.px ) + { + if( px != 0 ) intrusive_ptr_add_ref( px ); + } + + ~intrusive_ptr() + { + if( px != 0 ) intrusive_ptr_release( px ); + } + +#if !defined(BOOST_NO_MEMBER_TEMPLATES) || defined(BOOST_MSVC6_MEMBER_TEMPLATES) + + template intrusive_ptr & operator=(intrusive_ptr const & rhs) + { + this_type(rhs).swap(*this); + return *this; + } + +#endif + +// Move support + +#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES ) + + intrusive_ptr(intrusive_ptr && rhs) BOOST_NOEXCEPT : px( rhs.px ) + { + rhs.px = 0; + } + + intrusive_ptr & operator=(intrusive_ptr && rhs) BOOST_NOEXCEPT + { + this_type( static_cast< intrusive_ptr && >( rhs ) ).swap(*this); + return *this; + } + +#endif + + intrusive_ptr & operator=(intrusive_ptr const & rhs) + { + this_type(rhs).swap(*this); + return *this; + } + + intrusive_ptr & operator=(T * rhs) + { + this_type(rhs).swap(*this); + return *this; + } + + void reset() BOOST_NOEXCEPT + { + this_type().swap( *this ); + } + + void reset( T * rhs ) + { + this_type( rhs ).swap( *this ); + } + + void reset( T * rhs, bool add_ref ) + { + this_type( rhs, add_ref ).swap( *this ); + } + + T * get() const BOOST_NOEXCEPT + { + return px; + } + + T * detach() BOOST_NOEXCEPT + { + T * ret = px; + px = 0; + return ret; + } + + T & operator*() const + { + BOOST_ASSERT( px != 0 ); + return *px; + } + + T * operator->() const + { + BOOST_ASSERT( px != 0 ); + return px; + } + +// implicit conversion to "bool" +#include + + void swap(intrusive_ptr & rhs) BOOST_NOEXCEPT + { + T * tmp = px; + px = rhs.px; + rhs.px = tmp; + } + +private: + + T * px; +}; + +template inline bool operator==(intrusive_ptr const & a, intrusive_ptr const & b) +{ + return a.get() == b.get(); +} + +template inline bool operator!=(intrusive_ptr const & a, intrusive_ptr const & b) +{ + return a.get() != b.get(); +} + +template inline bool operator==(intrusive_ptr const & a, U * b) +{ + return a.get() == b; +} + +template inline bool operator!=(intrusive_ptr const & a, U * b) +{ + return a.get() != b; +} + +template inline bool operator==(T * a, intrusive_ptr const & b) +{ + return a == b.get(); +} + +template inline bool operator!=(T * a, intrusive_ptr const & b) +{ + return a != b.get(); +} + +#if __GNUC__ == 2 && __GNUC_MINOR__ <= 96 + +// Resolve the ambiguity between our op!= and the one in rel_ops + +template inline bool operator!=(intrusive_ptr const & a, intrusive_ptr const & b) +{ + return a.get() != b.get(); +} + +#endif + +#if !defined( BOOST_NO_CXX11_NULLPTR ) + +template inline bool operator==( intrusive_ptr const & p, boost::detail::sp_nullptr_t ) BOOST_NOEXCEPT +{ + return p.get() == 0; +} + +template inline bool operator==( boost::detail::sp_nullptr_t, intrusive_ptr const & p ) BOOST_NOEXCEPT +{ + return p.get() == 0; +} + +template inline bool operator!=( intrusive_ptr const & p, boost::detail::sp_nullptr_t ) BOOST_NOEXCEPT +{ + return p.get() != 0; +} + +template inline bool operator!=( boost::detail::sp_nullptr_t, intrusive_ptr const & p ) BOOST_NOEXCEPT +{ + return p.get() != 0; +} + +#endif + +template inline bool operator<(intrusive_ptr const & a, intrusive_ptr const & b) +{ + return std::less()(a.get(), b.get()); +} + +template void swap(intrusive_ptr & lhs, intrusive_ptr & rhs) +{ + lhs.swap(rhs); +} + +// mem_fn support + +template T * get_pointer(intrusive_ptr const & p) +{ + return p.get(); +} + +template intrusive_ptr static_pointer_cast(intrusive_ptr const & p) +{ + return static_cast(p.get()); +} + +template intrusive_ptr const_pointer_cast(intrusive_ptr const & p) +{ + return const_cast(p.get()); +} + +template intrusive_ptr dynamic_pointer_cast(intrusive_ptr const & p) +{ + return dynamic_cast(p.get()); +} + +// operator<< + +#if !defined(BOOST_NO_IOSTREAM) + +#if defined(BOOST_NO_TEMPLATED_IOSTREAMS) || ( defined(__GNUC__) && (__GNUC__ < 3) ) + +template std::ostream & operator<< (std::ostream & os, intrusive_ptr const & p) +{ + os << p.get(); + return os; +} + +#else + +// in STLport's no-iostreams mode no iostream symbols can be used +#ifndef _STLP_NO_IOSTREAMS + +# if defined(BOOST_MSVC) && BOOST_WORKAROUND(BOOST_MSVC, < 1300 && __SGI_STL_PORT) +// MSVC6 has problems finding std::basic_ostream through the using declaration in namespace _STL +using std::basic_ostream; +template basic_ostream & operator<< (basic_ostream & os, intrusive_ptr const & p) +# else +template std::basic_ostream & operator<< (std::basic_ostream & os, intrusive_ptr const & p) +# endif +{ + os << p.get(); + return os; +} + +#endif // _STLP_NO_IOSTREAMS + +#endif // __GNUC__ < 3 + +#endif // !defined(BOOST_NO_IOSTREAM) + +// hash_value + +template< class T > struct hash; + +template< class T > std::size_t hash_value( boost::intrusive_ptr const & p ) +{ + return boost::hash< T* >()( p.get() ); +} + +} // namespace boost + +#endif // #ifndef BOOST_SMART_PTR_INTRUSIVE_PTR_HPP_INCLUDED