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