sp_counted_impl.hpp 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309
  1. #ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_IMPL_HPP_INCLUDED
  2. #define BOOST_SMART_PTR_DETAIL_SP_COUNTED_IMPL_HPP_INCLUDED
  3. // MS compatible compilers support #pragma once
  4. #if defined(_MSC_VER) && (_MSC_VER >= 1020)
  5. # pragma once
  6. #endif
  7. //
  8. // detail/sp_counted_impl.hpp
  9. //
  10. // Copyright (c) 2001, 2002, 2003 Peter Dimov and Multi Media Ltd.
  11. // Copyright 2004-2005 Peter Dimov
  12. //
  13. // Distributed under the Boost Software License, Version 1.0. (See
  14. // accompanying file LICENSE_1_0.txt or copy at
  15. // http://www.boost.org/LICENSE_1_0.txt)
  16. //
  17. #if defined(BOOST_SP_USE_STD_ALLOCATOR) && defined(BOOST_SP_USE_QUICK_ALLOCATOR)
  18. # error BOOST_SP_USE_STD_ALLOCATOR and BOOST_SP_USE_QUICK_ALLOCATOR are incompatible.
  19. #endif
  20. #include <boost/smart_ptr/detail/sp_counted_base.hpp>
  21. #include <boost/smart_ptr/detail/sp_noexcept.hpp>
  22. #include <boost/core/checked_delete.hpp>
  23. #include <boost/core/addressof.hpp>
  24. #include <boost/config.hpp>
  25. #if defined(BOOST_SP_USE_QUICK_ALLOCATOR)
  26. #include <boost/smart_ptr/detail/quick_allocator.hpp>
  27. #endif
  28. #include <memory> // std::allocator, std::allocator_traits
  29. #include <cstddef> // std::size_t
  30. namespace boost
  31. {
  32. #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
  33. void sp_scalar_constructor_hook( void * px, std::size_t size, void * pn );
  34. void sp_scalar_destructor_hook( void * px, std::size_t size, void * pn );
  35. #endif
  36. namespace detail
  37. {
  38. // get_local_deleter
  39. template<class D> class local_sp_deleter;
  40. template<class D> D * get_local_deleter( D * /*p*/ ) BOOST_SP_NOEXCEPT
  41. {
  42. return 0;
  43. }
  44. template<class D> D * get_local_deleter( local_sp_deleter<D> * p ) BOOST_SP_NOEXCEPT;
  45. //
  46. template<class X> class BOOST_SYMBOL_VISIBLE sp_counted_impl_p: public sp_counted_base
  47. {
  48. private:
  49. X * px_;
  50. sp_counted_impl_p( sp_counted_impl_p const & );
  51. sp_counted_impl_p & operator= ( sp_counted_impl_p const & );
  52. typedef sp_counted_impl_p<X> this_type;
  53. public:
  54. explicit sp_counted_impl_p( X * px ): px_( px )
  55. {
  56. #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
  57. boost::sp_scalar_constructor_hook( px, sizeof(X), this );
  58. #endif
  59. }
  60. void dispose() BOOST_SP_NOEXCEPT BOOST_OVERRIDE
  61. {
  62. #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
  63. boost::sp_scalar_destructor_hook( px_, sizeof(X), this );
  64. #endif
  65. boost::checked_delete( px_ );
  66. }
  67. void * get_deleter( sp_typeinfo_ const & ) BOOST_SP_NOEXCEPT BOOST_OVERRIDE
  68. {
  69. return 0;
  70. }
  71. void * get_local_deleter( sp_typeinfo_ const & ) BOOST_SP_NOEXCEPT BOOST_OVERRIDE
  72. {
  73. return 0;
  74. }
  75. void * get_untyped_deleter() BOOST_SP_NOEXCEPT BOOST_OVERRIDE
  76. {
  77. return 0;
  78. }
  79. #if defined(BOOST_SP_USE_STD_ALLOCATOR)
  80. void * operator new( std::size_t )
  81. {
  82. return std::allocator<this_type>().allocate( 1, static_cast<this_type *>(0) );
  83. }
  84. void operator delete( void * p )
  85. {
  86. std::allocator<this_type>().deallocate( static_cast<this_type *>(p), 1 );
  87. }
  88. #endif
  89. #if defined(BOOST_SP_USE_QUICK_ALLOCATOR)
  90. void * operator new( std::size_t )
  91. {
  92. return quick_allocator<this_type>::alloc();
  93. }
  94. void operator delete( void * p )
  95. {
  96. quick_allocator<this_type>::dealloc( p );
  97. }
  98. #endif
  99. };
  100. //
  101. // Borland's Codeguard trips up over the -Vx- option here:
  102. //
  103. #ifdef __CODEGUARD__
  104. # pragma option push -Vx-
  105. #endif
  106. template<class P, class D> class BOOST_SYMBOL_VISIBLE sp_counted_impl_pd: public sp_counted_base
  107. {
  108. private:
  109. P ptr; // copy constructor must not throw
  110. D del; // copy/move constructor must not throw
  111. sp_counted_impl_pd( sp_counted_impl_pd const & );
  112. sp_counted_impl_pd & operator= ( sp_counted_impl_pd const & );
  113. typedef sp_counted_impl_pd<P, D> this_type;
  114. public:
  115. // pre: d(p) must not throw
  116. #if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
  117. sp_counted_impl_pd( P p, D & d ): ptr( p ), del( static_cast< D&& >( d ) )
  118. {
  119. }
  120. #else
  121. sp_counted_impl_pd( P p, D & d ): ptr( p ), del( d )
  122. {
  123. }
  124. #endif
  125. sp_counted_impl_pd( P p ): ptr( p ), del()
  126. {
  127. }
  128. void dispose() BOOST_SP_NOEXCEPT BOOST_OVERRIDE
  129. {
  130. del( ptr );
  131. }
  132. void * get_deleter( sp_typeinfo_ const & ti ) BOOST_SP_NOEXCEPT BOOST_OVERRIDE
  133. {
  134. return ti == BOOST_SP_TYPEID_(D)? &reinterpret_cast<char&>( del ): 0;
  135. }
  136. void * get_local_deleter( sp_typeinfo_ const & ti ) BOOST_SP_NOEXCEPT BOOST_OVERRIDE
  137. {
  138. return ti == BOOST_SP_TYPEID_(D)? boost::detail::get_local_deleter( boost::addressof( del ) ): 0;
  139. }
  140. void * get_untyped_deleter() BOOST_SP_NOEXCEPT BOOST_OVERRIDE
  141. {
  142. return &reinterpret_cast<char&>( del );
  143. }
  144. #if defined(BOOST_SP_USE_STD_ALLOCATOR)
  145. void * operator new( std::size_t )
  146. {
  147. return std::allocator<this_type>().allocate( 1, static_cast<this_type *>(0) );
  148. }
  149. void operator delete( void * p )
  150. {
  151. std::allocator<this_type>().deallocate( static_cast<this_type *>(p), 1 );
  152. }
  153. #endif
  154. #if defined(BOOST_SP_USE_QUICK_ALLOCATOR)
  155. void * operator new( std::size_t )
  156. {
  157. return quick_allocator<this_type>::alloc();
  158. }
  159. void operator delete( void * p )
  160. {
  161. quick_allocator<this_type>::dealloc( p );
  162. }
  163. #endif
  164. };
  165. template<class P, class D, class A> class BOOST_SYMBOL_VISIBLE sp_counted_impl_pda: public sp_counted_base
  166. {
  167. private:
  168. P p_; // copy constructor must not throw
  169. D d_; // copy/move constructor must not throw
  170. A a_; // copy constructor must not throw
  171. sp_counted_impl_pda( sp_counted_impl_pda const & );
  172. sp_counted_impl_pda & operator= ( sp_counted_impl_pda const & );
  173. typedef sp_counted_impl_pda<P, D, A> this_type;
  174. public:
  175. // pre: d( p ) must not throw
  176. #if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
  177. sp_counted_impl_pda( P p, D & d, A a ): p_( p ), d_( static_cast< D&& >( d ) ), a_( a )
  178. {
  179. }
  180. #else
  181. sp_counted_impl_pda( P p, D & d, A a ): p_( p ), d_( d ), a_( a )
  182. {
  183. }
  184. #endif
  185. sp_counted_impl_pda( P p, A a ): p_( p ), d_( a ), a_( a )
  186. {
  187. }
  188. void dispose() BOOST_SP_NOEXCEPT BOOST_OVERRIDE
  189. {
  190. d_( p_ );
  191. }
  192. void destroy() BOOST_SP_NOEXCEPT BOOST_OVERRIDE
  193. {
  194. #if !defined( BOOST_NO_CXX11_ALLOCATOR )
  195. typedef typename std::allocator_traits<A>::template rebind_alloc< this_type > A2;
  196. #else
  197. typedef typename A::template rebind< this_type >::other A2;
  198. #endif
  199. A2 a2( a_ );
  200. this->~this_type();
  201. a2.deallocate( this, 1 );
  202. }
  203. void * get_deleter( sp_typeinfo_ const & ti ) BOOST_SP_NOEXCEPT BOOST_OVERRIDE
  204. {
  205. return ti == BOOST_SP_TYPEID_( D )? &reinterpret_cast<char&>( d_ ): 0;
  206. }
  207. void * get_local_deleter( sp_typeinfo_ const & ti ) BOOST_SP_NOEXCEPT BOOST_OVERRIDE
  208. {
  209. return ti == BOOST_SP_TYPEID_( D )? boost::detail::get_local_deleter( boost::addressof( d_ ) ): 0;
  210. }
  211. void * get_untyped_deleter() BOOST_SP_NOEXCEPT BOOST_OVERRIDE
  212. {
  213. return &reinterpret_cast<char&>( d_ );
  214. }
  215. };
  216. #ifdef __CODEGUARD__
  217. # pragma option pop
  218. #endif
  219. } // namespace detail
  220. } // namespace boost
  221. #endif // #ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_IMPL_HPP_INCLUDED