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