make_local_shared_object.hpp 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200
  1. #ifndef BOOST_SMART_PTR_MAKE_LOCAL_SHARED_OBJECT_HPP_INCLUDED
  2. #define BOOST_SMART_PTR_MAKE_LOCAL_SHARED_OBJECT_HPP_INCLUDED
  3. // make_local_shared_object.hpp
  4. //
  5. // Copyright 2017 Peter Dimov
  6. //
  7. // Distributed under the Boost Software License, Version 1.0.
  8. // See accompanying file LICENSE_1_0.txt or copy at
  9. // http://www.boost.org/LICENSE_1_0.txt
  10. //
  11. // See http://www.boost.org/libs/smart_ptr/ for documentation.
  12. #include <boost/smart_ptr/local_shared_ptr.hpp>
  13. #include <boost/smart_ptr/make_shared.hpp>
  14. #include <boost/config.hpp>
  15. #include <utility>
  16. #include <cstddef>
  17. namespace boost
  18. {
  19. namespace detail
  20. {
  21. // lsp_if_not_array
  22. template<class T> struct lsp_if_not_array
  23. {
  24. typedef boost::local_shared_ptr<T> type;
  25. };
  26. template<class T> struct lsp_if_not_array<T[]>
  27. {
  28. };
  29. template<class T, std::size_t N> struct lsp_if_not_array<T[N]>
  30. {
  31. };
  32. // lsp_ms_deleter
  33. template<class T, class A> class lsp_ms_deleter: public local_counted_impl_em
  34. {
  35. private:
  36. typedef typename sp_aligned_storage<sizeof(T), ::boost::alignment_of<T>::value>::type storage_type;
  37. storage_type storage_;
  38. A a_;
  39. bool initialized_;
  40. private:
  41. void destroy() BOOST_SP_NOEXCEPT
  42. {
  43. if( initialized_ )
  44. {
  45. T * p = reinterpret_cast< T* >( storage_.data_ );
  46. #if !defined( BOOST_NO_CXX11_ALLOCATOR )
  47. std::allocator_traits<A>::destroy( a_, p );
  48. #else
  49. p->~T();
  50. #endif
  51. initialized_ = false;
  52. }
  53. }
  54. public:
  55. explicit lsp_ms_deleter( A const & a ) BOOST_SP_NOEXCEPT : a_( a ), initialized_( false )
  56. {
  57. }
  58. // optimization: do not copy storage_
  59. lsp_ms_deleter( lsp_ms_deleter const & r ) BOOST_SP_NOEXCEPT : a_( r.a_), initialized_( false )
  60. {
  61. }
  62. ~lsp_ms_deleter() BOOST_SP_NOEXCEPT
  63. {
  64. destroy();
  65. }
  66. void operator()( T * ) BOOST_SP_NOEXCEPT
  67. {
  68. destroy();
  69. }
  70. static void operator_fn( T* ) BOOST_SP_NOEXCEPT // operator() can't be static
  71. {
  72. }
  73. void * address() BOOST_SP_NOEXCEPT
  74. {
  75. return storage_.data_;
  76. }
  77. void set_initialized() BOOST_SP_NOEXCEPT
  78. {
  79. initialized_ = true;
  80. }
  81. };
  82. } // namespace detail
  83. template<class T, class A, class... Args> typename boost::detail::lsp_if_not_array<T>::type allocate_local_shared( A const & a, Args&&... args )
  84. {
  85. #if !defined( BOOST_NO_CXX11_ALLOCATOR )
  86. typedef typename std::allocator_traits<A>::template rebind_alloc<T> A2;
  87. #else
  88. typedef typename A::template rebind<T>::other A2;
  89. #endif
  90. A2 a2( a );
  91. typedef boost::detail::lsp_ms_deleter<T, A2> D;
  92. boost::shared_ptr<T> pt( static_cast< T* >( 0 ), boost::detail::sp_inplace_tag<D>(), a2 );
  93. D * pd = static_cast< D* >( pt._internal_get_untyped_deleter() );
  94. void * pv = pd->address();
  95. #if !defined( BOOST_NO_CXX11_ALLOCATOR )
  96. std::allocator_traits<A2>::construct( a2, static_cast< T* >( pv ), std::forward<Args>( args )... );
  97. #else
  98. ::new( pv ) T( std::forward<Args>( args )... );
  99. #endif
  100. pd->set_initialized();
  101. T * pt2 = static_cast< T* >( pv );
  102. boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
  103. pd->pn_ = pt._internal_count();
  104. return boost::local_shared_ptr<T>( boost::detail::lsp_internal_constructor_tag(), pt2, pd );
  105. }
  106. template<class T, class A> typename boost::detail::lsp_if_not_array<T>::type allocate_local_shared_noinit( A const & a )
  107. {
  108. #if !defined( BOOST_NO_CXX11_ALLOCATOR )
  109. typedef typename std::allocator_traits<A>::template rebind_alloc<T> A2;
  110. #else
  111. typedef typename A::template rebind<T>::other A2;
  112. #endif
  113. A2 a2( a );
  114. typedef boost::detail::lsp_ms_deleter< T, std::allocator<T> > D;
  115. boost::shared_ptr<T> pt( static_cast< T* >( 0 ), boost::detail::sp_inplace_tag<D>(), a2 );
  116. D * pd = static_cast< D* >( pt._internal_get_untyped_deleter() );
  117. void * pv = pd->address();
  118. ::new( pv ) T;
  119. pd->set_initialized();
  120. T * pt2 = static_cast< T* >( pv );
  121. boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
  122. pd->pn_ = pt._internal_count();
  123. return boost::local_shared_ptr<T>( boost::detail::lsp_internal_constructor_tag(), pt2, pd );
  124. }
  125. template<class T, class... Args> typename boost::detail::lsp_if_not_array<T>::type make_local_shared( Args&&... args )
  126. {
  127. return boost::allocate_local_shared<T>( std::allocator<T>(), std::forward<Args>(args)... );
  128. }
  129. template<class T> typename boost::detail::lsp_if_not_array<T>::type make_local_shared_noinit()
  130. {
  131. return boost::allocate_shared_noinit<T>( std::allocator<T>() );
  132. }
  133. } // namespace boost
  134. #endif // #ifndef BOOST_SMART_PTR_MAKE_SHARED_OBJECT_HPP_INCLUDED