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