Line data Source code
1 : #ifndef BOOST_SMART_PTR_SHARED_ARRAY_HPP_INCLUDED
2 : #define BOOST_SMART_PTR_SHARED_ARRAY_HPP_INCLUDED
3 :
4 : //
5 : // shared_array.hpp
6 : //
7 : // (C) Copyright Greg Colvin and Beman Dawes 1998, 1999.
8 : // Copyright (c) 2001, 2002, 2012 Peter Dimov
9 : //
10 : // Distributed under the Boost Software License, Version 1.0. (See
11 : // accompanying file LICENSE_1_0.txt or copy at
12 : // http://www.boost.org/LICENSE_1_0.txt)
13 : //
14 : // See http://www.boost.org/libs/smart_ptr/ for documentation.
15 : //
16 :
17 : #include <boost/config.hpp> // for broken compiler workarounds
18 :
19 : #include <memory> // TR1 cyclic inclusion fix
20 :
21 : #include <boost/assert.hpp>
22 : #include <boost/checked_delete.hpp>
23 :
24 : #include <boost/smart_ptr/shared_ptr.hpp>
25 : #include <boost/smart_ptr/detail/shared_count.hpp>
26 : #include <boost/smart_ptr/detail/sp_nullptr_t.hpp>
27 : #include <boost/smart_ptr/detail/sp_noexcept.hpp>
28 : #include <boost/detail/workaround.hpp>
29 :
30 : #include <cstddef> // for std::ptrdiff_t
31 : #include <algorithm> // for std::swap
32 : #include <functional> // for std::less
33 :
34 : namespace boost
35 : {
36 :
37 : //
38 : // shared_array
39 : //
40 : // shared_array extends shared_ptr to arrays.
41 : // The array pointed to is deleted when the last shared_array pointing to it
42 : // is destroyed or reset.
43 : //
44 :
45 0 : template<class T> class shared_array
46 : {
47 : private:
48 :
49 : // Borland 5.5.1 specific workarounds
50 : typedef checked_array_deleter<T> deleter;
51 : typedef shared_array<T> this_type;
52 :
53 : public:
54 :
55 : typedef T element_type;
56 :
57 : shared_array() BOOST_SP_NOEXCEPT : px( 0 ), pn()
58 : {
59 : }
60 :
61 : #if !defined( BOOST_NO_CXX11_NULLPTR )
62 :
63 : shared_array( boost::detail::sp_nullptr_t ) BOOST_SP_NOEXCEPT : px( 0 ), pn()
64 : {
65 : }
66 :
67 : #endif
68 :
69 : template<class Y>
70 0 : explicit shared_array( Y * p ): px( p ), pn( p, checked_array_deleter<Y>() )
71 : {
72 : boost::detail::sp_assert_convertible< Y[], T[] >();
73 : }
74 :
75 : //
76 : // Requirements: D's copy constructor must not throw
77 : //
78 : // shared_array will release p by calling d(p)
79 : //
80 :
81 : template<class Y, class D> shared_array( Y * p, D d ): px( p ), pn( p, d )
82 : {
83 : boost::detail::sp_assert_convertible< Y[], T[] >();
84 : }
85 :
86 : // As above, but with allocator. A's copy constructor shall not throw.
87 :
88 : template<class Y, class D, class A> shared_array( Y * p, D d, A a ): px( p ), pn( p, d, a )
89 : {
90 : boost::detail::sp_assert_convertible< Y[], T[] >();
91 : }
92 :
93 : // generated copy constructor, destructor are fine...
94 :
95 : #if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
96 :
97 : // ... except in C++0x, move disables the implicit copy
98 :
99 0 : shared_array( shared_array const & r ) BOOST_SP_NOEXCEPT : px( r.px ), pn( r.pn )
100 : {
101 : }
102 :
103 : shared_array( shared_array && r ) BOOST_SP_NOEXCEPT : px( r.px ), pn()
104 : {
105 : pn.swap( r.pn );
106 : r.px = 0;
107 : }
108 :
109 : #endif
110 :
111 : // conversion
112 :
113 : template<class Y>
114 : #if !defined( BOOST_SP_NO_SP_CONVERTIBLE )
115 :
116 : shared_array( shared_array<Y> const & r, typename boost::detail::sp_enable_if_convertible< Y[], T[] >::type = boost::detail::sp_empty() )
117 :
118 : #else
119 :
120 : shared_array( shared_array<Y> const & r )
121 :
122 : #endif
123 : BOOST_SP_NOEXCEPT : px( r.px ), pn( r.pn )
124 : {
125 : boost::detail::sp_assert_convertible< Y[], T[] >();
126 : }
127 :
128 : // aliasing
129 :
130 : template< class Y >
131 : shared_array( shared_array<Y> const & r, element_type * p ) BOOST_SP_NOEXCEPT : px( p ), pn( r.pn )
132 : {
133 : }
134 :
135 : // assignment
136 :
137 : shared_array & operator=( shared_array const & r ) BOOST_SP_NOEXCEPT
138 : {
139 : this_type( r ).swap( *this );
140 : return *this;
141 : }
142 :
143 : #if !defined(BOOST_MSVC) || (BOOST_MSVC >= 1400)
144 :
145 : template<class Y>
146 : shared_array & operator=( shared_array<Y> const & r ) BOOST_SP_NOEXCEPT
147 : {
148 : this_type( r ).swap( *this );
149 : return *this;
150 : }
151 :
152 : #endif
153 :
154 : #if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
155 :
156 : shared_array & operator=( shared_array && r ) BOOST_SP_NOEXCEPT
157 : {
158 : this_type( static_cast< shared_array && >( r ) ).swap( *this );
159 : return *this;
160 : }
161 :
162 : template<class Y>
163 : shared_array & operator=( shared_array<Y> && r ) BOOST_SP_NOEXCEPT
164 : {
165 : this_type( static_cast< shared_array<Y> && >( r ) ).swap( *this );
166 : return *this;
167 : }
168 :
169 : #endif
170 :
171 : void reset() BOOST_SP_NOEXCEPT
172 : {
173 : this_type().swap( *this );
174 : }
175 :
176 : template<class Y> void reset( Y * p ) // Y must be complete
177 : {
178 : BOOST_ASSERT( p == 0 || p != px ); // catch self-reset errors
179 : this_type( p ).swap( *this );
180 : }
181 :
182 : template<class Y, class D> void reset( Y * p, D d )
183 : {
184 : this_type( p, d ).swap( *this );
185 : }
186 :
187 : template<class Y, class D, class A> void reset( Y * p, D d, A a )
188 : {
189 : this_type( p, d, a ).swap( *this );
190 : }
191 :
192 : template<class Y> void reset( shared_array<Y> const & r, element_type * p ) BOOST_SP_NOEXCEPT
193 : {
194 : this_type( r, p ).swap( *this );
195 : }
196 :
197 : T & operator[] (std::ptrdiff_t i) const BOOST_SP_NOEXCEPT_WITH_ASSERT
198 : {
199 : BOOST_ASSERT(px != 0);
200 : BOOST_ASSERT(i >= 0);
201 : return px[i];
202 : }
203 :
204 0 : T * get() const BOOST_SP_NOEXCEPT
205 : {
206 : return px;
207 : }
208 :
209 : // implicit conversion to "bool"
210 : #include <boost/smart_ptr/detail/operator_bool.hpp>
211 :
212 : bool unique() const BOOST_SP_NOEXCEPT
213 : {
214 : return pn.unique();
215 : }
216 :
217 : long use_count() const BOOST_SP_NOEXCEPT
218 : {
219 : return pn.use_count();
220 : }
221 :
222 : void swap(shared_array<T> & other) BOOST_SP_NOEXCEPT
223 : {
224 : std::swap(px, other.px);
225 : pn.swap(other.pn);
226 : }
227 :
228 : void * _internal_get_deleter( boost::detail::sp_typeinfo_ const & ti ) const BOOST_SP_NOEXCEPT
229 : {
230 : return pn.get_deleter( ti );
231 : }
232 :
233 : private:
234 :
235 : template<class Y> friend class shared_array;
236 :
237 : T * px; // contained pointer
238 : detail::shared_count pn; // reference counter
239 :
240 : }; // shared_array
241 :
242 : template<class T> inline bool operator==(shared_array<T> const & a, shared_array<T> const & b) BOOST_SP_NOEXCEPT
243 : {
244 : return a.get() == b.get();
245 : }
246 :
247 : template<class T> inline bool operator!=(shared_array<T> const & a, shared_array<T> const & b) BOOST_SP_NOEXCEPT
248 : {
249 : return a.get() != b.get();
250 : }
251 :
252 : #if !defined( BOOST_NO_CXX11_NULLPTR )
253 :
254 : template<class T> inline bool operator==( shared_array<T> const & p, boost::detail::sp_nullptr_t ) BOOST_SP_NOEXCEPT
255 : {
256 : return p.get() == 0;
257 : }
258 :
259 : template<class T> inline bool operator==( boost::detail::sp_nullptr_t, shared_array<T> const & p ) BOOST_SP_NOEXCEPT
260 : {
261 : return p.get() == 0;
262 : }
263 :
264 : template<class T> inline bool operator!=( shared_array<T> const & p, boost::detail::sp_nullptr_t ) BOOST_SP_NOEXCEPT
265 : {
266 : return p.get() != 0;
267 : }
268 :
269 : template<class T> inline bool operator!=( boost::detail::sp_nullptr_t, shared_array<T> const & p ) BOOST_SP_NOEXCEPT
270 : {
271 : return p.get() != 0;
272 : }
273 :
274 : #endif
275 :
276 : template<class T> inline bool operator<(shared_array<T> const & a, shared_array<T> const & b) BOOST_SP_NOEXCEPT
277 : {
278 : return std::less<T*>()(a.get(), b.get());
279 : }
280 :
281 : template<class T> void swap(shared_array<T> & a, shared_array<T> & b) BOOST_SP_NOEXCEPT
282 : {
283 : a.swap(b);
284 : }
285 :
286 : template< class D, class T > D * get_deleter( shared_array<T> const & p ) BOOST_SP_NOEXCEPT
287 : {
288 : return static_cast< D * >( p._internal_get_deleter( BOOST_SP_TYPEID_(D) ) );
289 : }
290 :
291 : } // namespace boost
292 :
293 : #endif // #ifndef BOOST_SMART_PTR_SHARED_ARRAY_HPP_INCLUDED
|