• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #ifndef BOOST_SMART_PTR_MAKE_LOCAL_SHARED_OBJECT_HPP_INCLUDED
2 #define BOOST_SMART_PTR_MAKE_LOCAL_SHARED_OBJECT_HPP_INCLUDED
3 
4 //  make_local_shared_object.hpp
5 //
6 //  Copyright 2017 Peter Dimov
7 //
8 //  Distributed under the Boost Software License, Version 1.0.
9 //  See accompanying file LICENSE_1_0.txt or copy at
10 //  http://www.boost.org/LICENSE_1_0.txt
11 //
12 //  See http://www.boost.org/libs/smart_ptr/ for documentation.
13 
14 #include <boost/smart_ptr/local_shared_ptr.hpp>
15 #include <boost/smart_ptr/make_shared.hpp>
16 #include <boost/type_traits/remove_const.hpp>
17 #include <boost/config.hpp>
18 #include <utility>
19 #include <cstddef>
20 
21 namespace boost
22 {
23 
24 namespace detail
25 {
26 
27 // lsp_if_not_array
28 
29 template<class T> struct lsp_if_not_array
30 {
31     typedef boost::local_shared_ptr<T> type;
32 };
33 
34 template<class T> struct lsp_if_not_array<T[]>
35 {
36 };
37 
38 template<class T, std::size_t N> struct lsp_if_not_array<T[N]>
39 {
40 };
41 
42 // lsp_ms_deleter
43 
44 template<class T, class A> class lsp_ms_deleter: public local_counted_impl_em
45 {
46 private:
47 
48     typedef typename sp_aligned_storage<sizeof(T), ::boost::alignment_of<T>::value>::type storage_type;
49 
50     storage_type storage_;
51     A a_;
52     bool initialized_;
53 
54 private:
55 
destroy()56     void destroy() BOOST_SP_NOEXCEPT
57     {
58         if( initialized_ )
59         {
60             T * p = reinterpret_cast< T* >( storage_.data_ );
61 
62 #if !defined( BOOST_NO_CXX11_ALLOCATOR )
63 
64             std::allocator_traits<A>::destroy( a_, p );
65 
66 #else
67 
68             p->~T();
69 
70 #endif
71 
72             initialized_ = false;
73         }
74     }
75 
76 public:
77 
lsp_ms_deleter(A const & a)78     explicit lsp_ms_deleter( A const & a ) BOOST_SP_NOEXCEPT : a_( a ), initialized_( false )
79     {
80     }
81 
82     // optimization: do not copy storage_
lsp_ms_deleter(lsp_ms_deleter const & r)83     lsp_ms_deleter( lsp_ms_deleter const & r ) BOOST_SP_NOEXCEPT : a_( r.a_), initialized_( false )
84     {
85     }
86 
~lsp_ms_deleter()87     ~lsp_ms_deleter() BOOST_SP_NOEXCEPT
88     {
89         destroy();
90     }
91 
operator ()(T *)92     void operator()( T * ) BOOST_SP_NOEXCEPT
93     {
94         destroy();
95     }
96 
operator_fn(T *)97     static void operator_fn( T* ) BOOST_SP_NOEXCEPT // operator() can't be static
98     {
99     }
100 
address()101     void * address() BOOST_SP_NOEXCEPT
102     {
103         return storage_.data_;
104     }
105 
set_initialized()106     void set_initialized() BOOST_SP_NOEXCEPT
107     {
108         initialized_ = true;
109     }
110 };
111 
112 } // namespace detail
113 
allocate_local_shared(A const & a,Args &&...args)114 template<class T, class A, class... Args> typename boost::detail::lsp_if_not_array<T>::type allocate_local_shared( A const & a, Args&&... args )
115 {
116 #if !defined( BOOST_NO_CXX11_ALLOCATOR )
117 
118     typedef typename std::allocator_traits<A>::template rebind_alloc<T> A2;
119 
120 #else
121 
122     typedef typename A::template rebind<T>::other A2;
123 
124 #endif
125 
126     A2 a2( a );
127 
128     typedef boost::detail::lsp_ms_deleter<T, A2> D;
129 
130     boost::shared_ptr<T> pt( static_cast< T* >( 0 ), boost::detail::sp_inplace_tag<D>(), a2 );
131 
132     D * pd = static_cast< D* >( pt._internal_get_untyped_deleter() );
133     void * pv = pd->address();
134 
135 #if !defined( BOOST_NO_CXX11_ALLOCATOR )
136 
137     std::allocator_traits<A2>::construct( a2, static_cast< T* >( pv ), std::forward<Args>( args )... );
138 
139 #else
140 
141     ::new( pv ) T( std::forward<Args>( args )... );
142 
143 #endif
144 
145     pd->set_initialized();
146 
147     T * pt2 = static_cast< T* >( pv );
148     boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
149 
150     pd->pn_ = pt._internal_count();
151 
152     return boost::local_shared_ptr<T>( boost::detail::lsp_internal_constructor_tag(), pt2, pd );
153 }
154 
allocate_local_shared_noinit(A const & a)155 template<class T, class A> typename boost::detail::lsp_if_not_array<T>::type allocate_local_shared_noinit( A const & a )
156 {
157 #if !defined( BOOST_NO_CXX11_ALLOCATOR )
158 
159     typedef typename std::allocator_traits<A>::template rebind_alloc<T> A2;
160 
161 #else
162 
163     typedef typename A::template rebind<T>::other A2;
164 
165 #endif
166 
167     A2 a2( a );
168 
169     typedef boost::detail::lsp_ms_deleter< T, std::allocator<T> > D;
170 
171     boost::shared_ptr<T> pt( static_cast< T* >( 0 ), boost::detail::sp_inplace_tag<D>(), a2 );
172 
173     D * pd = static_cast< D* >( pt._internal_get_untyped_deleter() );
174     void * pv = pd->address();
175 
176     ::new( pv ) T;
177 
178     pd->set_initialized();
179 
180     T * pt2 = static_cast< T* >( pv );
181     boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
182 
183     pd->pn_ = pt._internal_count();
184 
185     return boost::local_shared_ptr<T>( boost::detail::lsp_internal_constructor_tag(), pt2, pd );
186 }
187 
make_local_shared(Args &&...args)188 template<class T, class... Args> typename boost::detail::lsp_if_not_array<T>::type make_local_shared( Args&&... args )
189 {
190     typedef typename boost::remove_const<T>::type T2;
191     return boost::allocate_local_shared<T2>( std::allocator<T2>(), std::forward<Args>(args)... );
192 }
193 
make_local_shared_noinit()194 template<class T> typename boost::detail::lsp_if_not_array<T>::type make_local_shared_noinit()
195 {
196     typedef typename boost::remove_const<T>::type T2;
197     return boost::allocate_shared_noinit<T2>( std::allocator<T2>() );
198 }
199 
200 } // namespace boost
201 
202 #endif // #ifndef BOOST_SMART_PTR_MAKE_SHARED_OBJECT_HPP_INCLUDED
203