]>
Commit | Line | Data |
---|---|---|
b758b22a BK |
1 | // <tr1/boost_shared_ptr.h> -*- C++ -*- |
2 | ||
3 | // Copyright (C) 2005 Free Software Foundation, Inc. | |
4 | // | |
5 | // This file is part of the GNU ISO C++ Library. This library is free | |
6 | // software; you can redistribute it and/or modify it under the | |
7 | // terms of the GNU General Public License as published by the | |
8 | // Free Software Foundation; either version 2, or (at your option) | |
9 | // any later version. | |
10 | ||
11 | // This library is distributed in the hope that it will be useful, | |
12 | // but WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
14 | // GNU General Public License for more details. | |
15 | ||
16 | // You should have received a copy of the GNU General Public License along | |
17 | // with this library; see the file COPYING. If not, write to the Free | |
83f51799 | 18 | // Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, |
b758b22a BK |
19 | // USA. |
20 | ||
21 | // As a special exception, you may use this file as part of a free software | |
22 | // library without restriction. Specifically, if other files instantiate | |
23 | // templates or use macros or inline functions from this file, or you compile | |
24 | // this file and link it with other files to produce an executable, this | |
25 | // file does not by itself cause the resulting executable to be covered by | |
26 | // the GNU General Public License. This exception does not however | |
27 | // invalidate any other reasons why the executable file might be covered by | |
28 | // the GNU General Public License. | |
29 | ||
30 | // shared_count.hpp | |
31 | // Copyright (c) 2001, 2002, 2003 Peter Dimov and Multi Media Ltd. | |
32 | ||
33 | // shared_ptr.hpp | |
34 | // Copyright (C) 1998, 1999 Greg Colvin and Beman Dawes. | |
35 | // Copyright (C) 2001, 2002, 2003 Peter Dimov | |
36 | ||
37 | // weak_ptr.hpp | |
38 | // Copyright (C) 2001, 2002, 2003 Peter Dimov | |
39 | ||
40 | // enable_shared_from_this.hpp | |
41 | // Copyright (C) 2002 Peter Dimov | |
42 | ||
43 | // Distributed under the Boost Software License, Version 1.0. (See | |
44 | // accompanying file LICENSE_1_0.txt or copy at | |
45 | // http://www.boost.org/LICENSE_1_0.txt) | |
46 | ||
47 | // GCC Note: based on version 1.32.0 of the Boost library. | |
48 | ||
49 | /** @file boost_memory.h | |
50 | * This is an internal header file, included by other library headers. | |
51 | * You should not attempt to use it directly. | |
52 | */ | |
53 | ||
54 | #ifndef _BOOST_SHARED_PTR_H | |
55 | #define _BOOST_SHARED_PTR_H 1 | |
56 | ||
57 | // namespace std::tr1 | |
58 | namespace std | |
59 | { | |
60 | namespace tr1 | |
61 | { | |
62 | ||
63 | class bad_weak_ptr : public std::exception | |
64 | { | |
65 | public: | |
66 | ||
81809516 PC |
67 | virtual char const* |
68 | what() const throw() | |
69 | { return "tr1::bad_weak_ptr"; } | |
b758b22a BK |
70 | }; |
71 | ||
72 | // Helper for exception objects in <tr1/memory> | |
73 | // TODO this should be defined in a different file. | |
74 | inline void | |
75 | __throw_bad_weak_ptr() | |
76 | { | |
77 | #if __EXCEPTIONS | |
78 | throw bad_weak_ptr(); | |
79 | #else | |
80 | std::abort(); | |
81 | #endif | |
82 | } | |
83 | ||
84 | ||
81809516 | 85 | template<typename _Tp> |
b758b22a BK |
86 | struct _Sp_deleter |
87 | { | |
88 | typedef void result_type; | |
89 | typedef _Tp* argument_type; | |
90 | ||
91 | void | |
92 | operator()(_Tp* p) const | |
93 | { delete p; } | |
94 | }; | |
95 | ||
96 | ||
97 | class _Sp_counted_base | |
98 | { | |
99 | public: | |
100 | ||
101 | _Sp_counted_base() | |
102 | : _M_use_count(1), _M_weak_count(1) | |
7010f39e JW |
103 | { |
104 | // For the case of __GTHREAD_MUTEX_INIT we haven't initialised | |
105 | // the mutex yet, so do it now. | |
106 | #if defined(__GTHREADS) && defined(__GTHREAD_MUTEX_INIT) | |
107 | __gthread_mutex_t __tmp = __GTHREAD_MUTEX_INIT; | |
108 | _M_mutex = __tmp; | |
109 | #endif | |
110 | } | |
b758b22a BK |
111 | |
112 | virtual | |
113 | ~_Sp_counted_base() // nothrow | |
114 | { } | |
115 | ||
116 | // dispose() is called when _M_use_count drops to zero, to release | |
117 | // the resources managed by *this. | |
118 | virtual void | |
119 | dispose() = 0; // nothrow | |
120 | ||
121 | // destroy() is called when _M_weak_count drops to zero. | |
122 | virtual void | |
123 | destroy() // nothrow | |
124 | { | |
125 | delete this; | |
126 | } | |
127 | ||
128 | virtual void* | |
129 | get_deleter(const std::type_info&) = 0; | |
130 | ||
131 | void | |
132 | add_ref_copy() | |
133 | { | |
134 | __gnu_cxx::__atomic_add(&_M_use_count, 1); | |
135 | } | |
136 | ||
137 | void | |
138 | add_ref_lock() | |
139 | { | |
fcec20a7 JW |
140 | __gnu_cxx::lock lock(_M_mutex); |
141 | if (__gnu_cxx::__exchange_and_add(&_M_use_count, 1) == 0) | |
81809516 PC |
142 | { |
143 | _M_use_count = 0; | |
144 | __throw_bad_weak_ptr(); | |
145 | } | |
b758b22a BK |
146 | } |
147 | ||
148 | void | |
149 | release() // nothrow | |
150 | { | |
fcec20a7 | 151 | if (__gnu_cxx::__exchange_and_add(&_M_use_count, -1) == 1) |
81809516 PC |
152 | { |
153 | dispose(); | |
7fd60218 PC |
154 | |
155 | _GLIBCXX_READ_MEM_BARRIER; | |
156 | _GLIBCXX_WRITE_MEM_BARRIER; | |
157 | ||
158 | if (__gnu_cxx::__exchange_and_add(&_M_weak_count, -1) == 1) | |
159 | destroy(); | |
81809516 | 160 | } |
b758b22a BK |
161 | } |
162 | ||
163 | void | |
164 | weak_add_ref() // nothrow | |
165 | { | |
166 | __gnu_cxx::__atomic_add(&_M_weak_count, 1); | |
167 | } | |
168 | ||
169 | void | |
170 | weak_release() // nothrow | |
171 | { | |
fcec20a7 | 172 | if (__gnu_cxx::__exchange_and_add(&_M_weak_count, -1) == 1) |
81809516 | 173 | { |
7fd60218 PC |
174 | _GLIBCXX_READ_MEM_BARRIER; |
175 | _GLIBCXX_WRITE_MEM_BARRIER; | |
81809516 PC |
176 | destroy(); |
177 | } | |
b758b22a BK |
178 | } |
179 | ||
180 | long | |
181 | use_count() const // nothrow | |
182 | { | |
183 | return _M_use_count; // XXX is this MT safe? | |
184 | } | |
185 | ||
186 | private: | |
187 | ||
188 | _Sp_counted_base(_Sp_counted_base const&); | |
81809516 | 189 | _Sp_counted_base& operator=(_Sp_counted_base const&); |
b758b22a BK |
190 | |
191 | _Atomic_word _M_use_count; // #shared | |
192 | _Atomic_word _M_weak_count; // #weak + (#shared != 0) | |
fcec20a7 | 193 | __gnu_cxx::mutex_type _M_mutex; |
b758b22a BK |
194 | }; |
195 | ||
81809516 PC |
196 | template<typename _Ptr, typename _Deleter> |
197 | class _Sp_counted_base_impl | |
198 | : public _Sp_counted_base | |
b758b22a | 199 | { |
81809516 | 200 | public: |
b758b22a | 201 | |
81809516 PC |
202 | /** |
203 | * @brief | |
204 | * @pre d(p) must not throw. | |
205 | */ | |
206 | _Sp_counted_base_impl(_Ptr __p, _Deleter __d) | |
207 | : _M_ptr(__p), _M_del(__d) | |
208 | { } | |
209 | ||
210 | virtual void | |
211 | dispose() // nothrow | |
212 | { | |
213 | _M_del(_M_ptr); | |
214 | } | |
215 | ||
216 | virtual void* | |
217 | get_deleter(const std::type_info& __ti) | |
218 | { | |
219 | return __ti == typeid(_Deleter) ? &_M_del : 0; | |
220 | } | |
221 | ||
222 | private: | |
223 | _Sp_counted_base_impl(const _Sp_counted_base_impl&); | |
224 | _Sp_counted_base_impl& operator=(const _Sp_counted_base_impl&); | |
225 | ||
226 | _Ptr _M_ptr; // copy constructor must not throw | |
227 | _Deleter _M_del; // copy constructor must not throw | |
228 | }; | |
b758b22a BK |
229 | |
230 | class weak_count; | |
231 | ||
232 | class shared_count | |
233 | { | |
234 | private: | |
235 | ||
236 | _Sp_counted_base* _M_pi; | |
237 | ||
238 | friend class weak_count; | |
239 | ||
240 | public: | |
241 | ||
242 | shared_count() | |
243 | : _M_pi(0) // nothrow | |
244 | { } | |
245 | ||
81809516 | 246 | template<typename _Ptr, typename _Deleter> |
b758b22a BK |
247 | shared_count(_Ptr __p, _Deleter __d) |
248 | : _M_pi(0) | |
249 | { | |
250 | try | |
81809516 PC |
251 | { |
252 | _M_pi = new _Sp_counted_base_impl<_Ptr, _Deleter>(__p, __d); | |
253 | } | |
b758b22a | 254 | catch(...) |
81809516 PC |
255 | { |
256 | __d(__p); // delete __p | |
257 | __throw_exception_again; | |
258 | } | |
b758b22a BK |
259 | } |
260 | ||
261 | // auto_ptr<_Tp> is special cased to provide the strong guarantee | |
262 | ||
81809516 | 263 | template<typename _Tp> |
b758b22a | 264 | explicit shared_count(std::auto_ptr<_Tp>& __r) |
81809516 PC |
265 | : _M_pi(new _Sp_counted_base_impl<_Tp*, |
266 | _Sp_deleter<_Tp> >(__r.get(), _Sp_deleter<_Tp>())) | |
b758b22a BK |
267 | { __r.release(); } |
268 | ||
269 | // throws bad_weak_ptr when __r.use_count() == 0 | |
270 | explicit shared_count(const weak_count& __r); | |
271 | ||
272 | ~shared_count() // nothrow | |
273 | { | |
274 | if (_M_pi != 0) | |
275 | _M_pi->release(); | |
276 | } | |
277 | ||
278 | shared_count(const shared_count& __r) | |
279 | : _M_pi(__r._M_pi) // nothrow | |
280 | { | |
281 | if (_M_pi != 0) | |
282 | _M_pi->add_ref_copy(); | |
283 | } | |
284 | ||
285 | shared_count& | |
286 | operator=(const shared_count& __r) // nothrow | |
287 | { | |
288 | _Sp_counted_base* __tmp = __r._M_pi; | |
289 | ||
290 | if(__tmp != _M_pi) | |
81809516 PC |
291 | { |
292 | if(__tmp != 0) | |
293 | __tmp->add_ref_copy(); | |
294 | if(_M_pi != 0) | |
295 | _M_pi->release(); | |
296 | _M_pi = __tmp; | |
297 | } | |
b758b22a BK |
298 | return *this; |
299 | } | |
300 | ||
301 | void swap(shared_count& __r) // nothrow | |
302 | { | |
303 | _Sp_counted_base* __tmp = __r._M_pi; | |
304 | __r._M_pi = _M_pi; | |
305 | _M_pi = __tmp; | |
306 | } | |
307 | ||
308 | long | |
309 | use_count() const // nothrow | |
310 | { return _M_pi != 0 ? _M_pi->use_count() : 0; } | |
311 | ||
312 | bool | |
313 | unique() const // nothrow | |
314 | { return this->use_count() == 1; } | |
315 | ||
316 | friend inline bool | |
317 | operator==(const shared_count& __a, const shared_count& __b) | |
318 | { return __a._M_pi == __b._M_pi; } | |
319 | ||
320 | friend inline bool | |
321 | operator<(const shared_count& __a, const shared_count& __b) | |
322 | { return std::less<_Sp_counted_base*>()(__a._M_pi, __b._M_pi); } | |
323 | ||
324 | void* | |
325 | get_deleter(const std::type_info& __ti) const | |
326 | { return _M_pi ? _M_pi->get_deleter(__ti) : 0; } | |
327 | }; | |
328 | ||
329 | ||
330 | class weak_count | |
331 | { | |
332 | private: | |
333 | ||
7fd60218 | 334 | _Sp_counted_base* _M_pi; |
b758b22a BK |
335 | |
336 | friend class shared_count; | |
337 | ||
338 | public: | |
339 | ||
340 | weak_count() | |
341 | : _M_pi(0) // nothrow | |
342 | { } | |
343 | ||
344 | weak_count(const shared_count& __r) | |
345 | : _M_pi(__r._M_pi) // nothrow | |
346 | { | |
347 | if (_M_pi != 0) | |
348 | _M_pi->weak_add_ref(); | |
349 | } | |
350 | ||
351 | weak_count(const weak_count& __r) | |
352 | : _M_pi(__r._M_pi) // nothrow | |
353 | { | |
354 | if (_M_pi != 0) | |
355 | _M_pi->weak_add_ref(); | |
356 | } | |
357 | ||
358 | ~weak_count() // nothrow | |
359 | { | |
360 | if (_M_pi != 0) | |
361 | _M_pi->weak_release(); | |
362 | } | |
363 | ||
364 | weak_count& | |
365 | operator=(const shared_count& __r) // nothrow | |
366 | { | |
367 | _Sp_counted_base* __tmp = __r._M_pi; | |
368 | if (__tmp != 0) | |
369 | __tmp->weak_add_ref(); | |
370 | if (_M_pi != 0) | |
371 | _M_pi->weak_release(); | |
372 | _M_pi = __tmp; | |
373 | ||
374 | return *this; | |
375 | } | |
376 | ||
377 | weak_count& | |
378 | operator=(const weak_count& __r) // nothrow | |
379 | { | |
380 | _Sp_counted_base * __tmp = __r._M_pi; | |
381 | if (__tmp != 0) | |
382 | __tmp->weak_add_ref(); | |
383 | if (_M_pi != 0) | |
384 | _M_pi->weak_release(); | |
385 | _M_pi = __tmp; | |
386 | ||
387 | return *this; | |
388 | } | |
389 | ||
390 | void | |
391 | swap(weak_count& __r) // nothrow | |
392 | { | |
393 | _Sp_counted_base * __tmp = __r._M_pi; | |
394 | __r._M_pi = _M_pi; | |
395 | _M_pi = __tmp; | |
396 | } | |
397 | ||
398 | long | |
399 | use_count() const // nothrow | |
400 | { return _M_pi != 0 ? _M_pi->use_count() : 0; } | |
401 | ||
402 | friend inline bool | |
403 | operator==(const weak_count& __a, const weak_count& __b) | |
404 | { return __a._M_pi == __b._M_pi; } | |
405 | ||
406 | friend inline bool | |
407 | operator<(const weak_count& __a, const weak_count& __b) | |
408 | { return std::less<_Sp_counted_base*>()(__a._M_pi, __b._M_pi); } | |
409 | }; | |
410 | ||
411 | inline | |
412 | shared_count::shared_count(const weak_count& __r) | |
413 | : _M_pi(__r._M_pi) | |
414 | { | |
415 | if (_M_pi != 0) | |
b758b22a | 416 | _M_pi->add_ref_lock(); |
b758b22a | 417 | else |
b758b22a | 418 | __throw_bad_weak_ptr(); |
b758b22a BK |
419 | } |
420 | ||
421 | // fwd decls | |
81809516 PC |
422 | template<typename _Tp> |
423 | class weak_ptr; | |
424 | ||
425 | template<typename _Tp> | |
426 | class enable_shared_from_this; | |
b758b22a BK |
427 | |
428 | struct __static_cast_tag {}; | |
429 | struct __const_cast_tag {}; | |
430 | struct __dynamic_cast_tag {}; | |
431 | struct __polymorphic_cast_tag {}; | |
432 | ||
81809516 PC |
433 | template<class _Tp> |
434 | struct shared_ptr_traits | |
435 | { typedef _Tp& reference; }; | |
b758b22a | 436 | |
81809516 PC |
437 | template<> |
438 | struct shared_ptr_traits<void> | |
439 | { typedef void reference; }; | |
b758b22a | 440 | |
81809516 PC |
441 | template<> |
442 | struct shared_ptr_traits<void const> | |
443 | { typedef void reference; }; | |
b758b22a | 444 | |
81809516 PC |
445 | template<> |
446 | struct shared_ptr_traits<void volatile> | |
447 | { typedef void reference; }; | |
b758b22a | 448 | |
81809516 PC |
449 | template<> |
450 | struct shared_ptr_traits<void const volatile> | |
451 | { typedef void reference; }; | |
b758b22a BK |
452 | |
453 | ||
454 | // enable_shared_from_this support | |
455 | ||
456 | // friend of enable_shared_from_this | |
81809516 | 457 | template<typename _Tp1, typename _Tp2> |
b758b22a | 458 | void |
81809516 PC |
459 | __enable_shared_from_this(const shared_count& __pn, |
460 | const enable_shared_from_this<_Tp1>* __pe, | |
461 | const _Tp2* __px ); | |
b758b22a BK |
462 | |
463 | inline void | |
464 | __enable_shared_from_this(const shared_count&, ...) | |
465 | { } | |
466 | ||
467 | /** | |
468 | * @class shared_ptr <tr1/memory> | |
469 | * | |
470 | * A smart pointer with reference-counted copy semantics. | |
471 | * The object pointed to is deleted when the last shared_ptr pointing to it | |
472 | * is destroyed or reset. | |
473 | */ | |
474 | ||
81809516 | 475 | template<typename _Tp> |
b758b22a BK |
476 | class shared_ptr |
477 | { | |
478 | typedef typename shared_ptr_traits<_Tp>::reference _Reference; | |
479 | ||
480 | public: | |
481 | ||
482 | typedef _Tp element_type; | |
483 | ||
484 | /** @brief Construct an empty %shared_ptr. | |
485 | * @post use_count()==0 && get()==0 | |
486 | */ | |
81809516 PC |
487 | shared_ptr() |
488 | : _M_ptr(0), _M_refcount() // never throws | |
b758b22a BK |
489 | { } |
490 | ||
491 | /** @brief Construct a %shared_ptr that owns the pointer @a p. | |
492 | * @param p A pointer that is convertible to element_type*. | |
81809516 | 493 | * @post use_count() == 1 && get() == p |
b758b22a BK |
494 | * @throw std::bad_alloc, in which case @c delete @a p is called. |
495 | */ | |
81809516 | 496 | template<typename _Tp1> |
b758b22a BK |
497 | explicit shared_ptr(_Tp1* __p) |
498 | : _M_ptr(__p), _M_refcount(__p, _Sp_deleter<_Tp1>()) | |
499 | { | |
500 | __glibcxx_function_requires(_ConvertibleConcept<_Tp1*, _Tp*>) | |
501 | // __glibcxx_function_requires(_CompleteConcept<_Tp1*>) | |
502 | ||
503 | __enable_shared_from_this( _M_refcount, __p, __p ); | |
504 | } | |
505 | ||
506 | // | |
507 | // Requirements: D's copy constructor and destructor must not throw | |
508 | // | |
509 | // shared_ptr will release p by calling d(p) | |
510 | // | |
511 | /** @brief Construct a %shared_ptr that owns the pointer @a p | |
512 | * and the deleter @a d. | |
513 | * @param p A pointer. | |
514 | * @param d A deleter. | |
81809516 | 515 | * @post use_count() == 1 && get() == p |
b758b22a BK |
516 | * @throw std::bad_alloc, in which case @a d(p) is called. |
517 | */ | |
81809516 | 518 | template<typename _Tp1, typename _Deleter> |
b758b22a BK |
519 | shared_ptr(_Tp1* __p, _Deleter __d) |
520 | : _M_ptr(__p), _M_refcount(__p, __d) | |
521 | { | |
522 | __glibcxx_function_requires(_ConvertibleConcept<_Tp1*, _Tp*>) | |
523 | // TODO requires D is CopyConstructible and d(p) well-formed | |
524 | ||
525 | __enable_shared_from_this( _M_refcount, __p, __p ); | |
526 | } | |
527 | ||
528 | // generated copy constructor, assignment, destructor are fine. | |
529 | ||
530 | /** @brief If @a r is empty, constructs an empty %shared_ptr; otherwise | |
531 | * construct a %shared_ptr that shares ownership with @a r. | |
532 | * @param r A %shared_ptr. | |
81809516 | 533 | * @post get() == r.get() && use_count() == r.use_count() |
b758b22a BK |
534 | * @throw std::bad_alloc, in which case |
535 | */ | |
81809516 | 536 | template<typename _Tp1> |
b758b22a BK |
537 | shared_ptr(const shared_ptr<_Tp1>& __r) |
538 | : _M_ptr(__r._M_ptr), _M_refcount(__r._M_refcount) // never throws | |
539 | { | |
540 | __glibcxx_function_requires(_ConvertibleConcept<_Tp1*, _Tp*>) | |
541 | } | |
542 | ||
543 | /** @brief Constructs a %shared_ptr that shares ownership with @a r | |
544 | * and stores a copy of the pointer stored in @a r. | |
545 | * @param r A weak_ptr. | |
81809516 | 546 | * @post use_count() == r.use_count() |
b758b22a BK |
547 | * @throw bad_weak_ptr when r.expired(), |
548 | * in which case the constructor has no effect. | |
549 | */ | |
81809516 | 550 | template<typename _Tp1> |
b758b22a BK |
551 | explicit shared_ptr(const weak_ptr<_Tp1>& __r) |
552 | : _M_refcount(__r._M_refcount) // may throw | |
553 | { | |
554 | __glibcxx_function_requires(_ConvertibleConcept<_Tp1*, _Tp*>) | |
555 | // it is now safe to copy r__._M_ptr, as _M_refcount(__r._M_refcount) | |
556 | // did not throw | |
557 | _M_ptr = __r._M_ptr; | |
558 | } | |
559 | ||
560 | /** | |
81809516 | 561 | * @post use_count() == 1 and r.get() == 0 |
b758b22a | 562 | */ |
81809516 | 563 | template<typename _Tp1> |
b758b22a BK |
564 | explicit shared_ptr(std::auto_ptr<_Tp1>& __r) |
565 | : _M_ptr(__r.get()), _M_refcount() | |
566 | { | |
567 | // TODO requires r.release() convertible to _Tp*, Tp1 is complete, | |
568 | // delete r.release() well-formed | |
569 | _Tp1 * __tmp = __r.get(); | |
570 | _M_refcount = shared_count(__r); | |
571 | ||
572 | __enable_shared_from_this( _M_refcount, __tmp, __tmp ); | |
573 | } | |
574 | ||
81809516 | 575 | template<typename _Tp1> |
b758b22a | 576 | shared_ptr(const shared_ptr<_Tp1>& __r, __static_cast_tag) |
81809516 PC |
577 | : _M_ptr(static_cast<element_type*>(__r._M_ptr)), |
578 | _M_refcount(__r._M_refcount) | |
b758b22a BK |
579 | { } |
580 | ||
81809516 | 581 | template<typename _Tp1> |
b758b22a | 582 | shared_ptr(const shared_ptr<_Tp1>& __r, __const_cast_tag) |
81809516 PC |
583 | : _M_ptr(const_cast<element_type*>(__r._M_ptr)), |
584 | _M_refcount(__r._M_refcount) | |
b758b22a BK |
585 | { } |
586 | ||
81809516 | 587 | template<typename _Tp1> |
b758b22a | 588 | shared_ptr(const shared_ptr<_Tp1>& __r, __dynamic_cast_tag) |
81809516 PC |
589 | : _M_ptr(dynamic_cast<element_type*>(__r._M_ptr)), |
590 | _M_refcount(__r._M_refcount) | |
b758b22a BK |
591 | { |
592 | if (_M_ptr == 0) // need to allocate new counter -- the cast failed | |
b758b22a | 593 | _M_refcount = shared_count(); |
b758b22a BK |
594 | } |
595 | ||
81809516 | 596 | template<typename _Tp1> |
b758b22a BK |
597 | shared_ptr& |
598 | operator=(const shared_ptr<_Tp1>& __r) // never throws | |
599 | { | |
600 | _M_ptr = __r._M_ptr; | |
601 | _M_refcount = __r._M_refcount; // shared_count::op= doesn't throw | |
602 | return *this; | |
603 | } | |
604 | ||
81809516 | 605 | template<typename _Tp1> |
b758b22a BK |
606 | shared_ptr& |
607 | operator=(std::auto_ptr<_Tp1>& __r) | |
608 | { | |
609 | shared_ptr(__r).swap(*this); | |
610 | return *this; | |
611 | } | |
612 | ||
613 | void | |
614 | reset() // never throws | |
615 | { shared_ptr().swap(*this); } | |
616 | ||
81809516 | 617 | template<typename _Tp1> |
b758b22a BK |
618 | void |
619 | reset(_Tp1* __p) // _Tp1 must be complete | |
620 | { | |
81809516 PC |
621 | _GLIBCXX_DEBUG_ASSERT(__p == 0 || __p != _M_ptr); // catch self-reset |
622 | // errors | |
b758b22a BK |
623 | shared_ptr(__p).swap(*this); |
624 | } | |
625 | ||
81809516 | 626 | template<typename _Tp1, typename _Deleter> |
b758b22a BK |
627 | void |
628 | reset(_Tp1 * __p, _Deleter __d) | |
629 | { shared_ptr(__p, __d).swap(*this); } | |
630 | ||
631 | // error to instantiate if _Tp is [cv-qual] void | |
632 | _Reference | |
633 | operator*() const // never throws | |
634 | { | |
635 | _GLIBCXX_DEBUG_ASSERT(_M_ptr != 0); | |
636 | return *_M_ptr; | |
637 | } | |
638 | ||
639 | _Tp* | |
640 | operator->() const // never throws | |
641 | { | |
642 | _GLIBCXX_DEBUG_ASSERT(_M_ptr != 0); | |
643 | return _M_ptr; | |
644 | } | |
645 | ||
646 | _Tp* | |
647 | get() const // never throws | |
648 | { return _M_ptr; } | |
649 | ||
650 | // implicit conversion to "bool" | |
651 | private: | |
652 | typedef _Tp* shared_ptr::*__unspecified_bool_type; | |
653 | ||
654 | public: | |
655 | operator __unspecified_bool_type() const // never throws | |
656 | { return _M_ptr == 0 ? 0 : &shared_ptr::_M_ptr; } | |
657 | ||
658 | bool | |
659 | unique() const // never throws | |
660 | { return _M_refcount.unique(); } | |
661 | ||
662 | long | |
663 | use_count() const // never throws | |
664 | { return _M_refcount.use_count(); } | |
665 | ||
666 | void | |
667 | swap(shared_ptr<_Tp>& __other) // never throws | |
668 | { | |
669 | std::swap(_M_ptr, __other._M_ptr); | |
670 | _M_refcount.swap(__other._M_refcount); | |
671 | } | |
672 | ||
27473454 PC |
673 | void* |
674 | _M_get_deleter(const std::type_info& __ti) const | |
675 | { return _M_refcount.get_deleter(__ti); } | |
676 | ||
b758b22a | 677 | private: |
81809516 | 678 | template<typename _Tp1> |
b758b22a BK |
679 | bool |
680 | _M_less(const shared_ptr<_Tp1>& __rhs) const | |
681 | { return _M_refcount < __rhs._M_refcount; } | |
682 | ||
7fd60218 PC |
683 | template<typename _Tp1> friend class shared_ptr; |
684 | template<typename _Tp1> friend class weak_ptr; | |
b758b22a BK |
685 | |
686 | // friends injected into enclosing namespace and found by ADL: | |
81809516 | 687 | template<typename _Tp1> |
b758b22a BK |
688 | friend inline bool |
689 | operator==(const shared_ptr& __a, const shared_ptr<_Tp1>& __b) | |
690 | { return __a.get() == __b.get(); } | |
691 | ||
81809516 | 692 | template<typename _Tp1> |
b758b22a BK |
693 | friend inline bool |
694 | operator!=(const shared_ptr& __a, const shared_ptr<_Tp1>& __b) | |
695 | { return __a.get() != __b.get(); } | |
696 | ||
81809516 | 697 | template<typename _Tp1> |
b758b22a BK |
698 | friend inline bool |
699 | operator<(const shared_ptr& __a, const shared_ptr<_Tp1>& __b) | |
700 | { return __a._M_less(__b); } | |
701 | ||
702 | _Tp* _M_ptr; // contained pointer | |
703 | shared_count _M_refcount; // reference counter | |
704 | }; // shared_ptr | |
705 | ||
706 | // 2.2.3.9 shared_ptr casts | |
707 | ||
708 | /** @warning The seemingly equivalent | |
709 | * <code>shared_ptr<T>(static_cast<T*>(r.get()))</code> | |
710 | * will eventually result in undefined behaviour, | |
711 | * attempting to delete the same object twice. | |
712 | */ | |
81809516 | 713 | template<typename _Tp, typename _Tp1> |
b758b22a BK |
714 | shared_ptr<_Tp> |
715 | static_pointer_cast(const shared_ptr<_Tp1>& __r) | |
716 | { | |
717 | return shared_ptr<_Tp>(__r, __static_cast_tag()); | |
718 | } | |
719 | ||
720 | /** @warning The seemingly equivalent | |
721 | * <code>shared_ptr<T>(const_cast<T*>(r.get()))</code> | |
722 | * will eventually result in undefined behaviour, | |
723 | * attempting to delete the same object twice. | |
724 | */ | |
81809516 | 725 | template<typename _Tp, typename _Tp1> |
b758b22a BK |
726 | shared_ptr<_Tp> |
727 | const_pointer_cast(const shared_ptr<_Tp1>& __r) | |
728 | { | |
729 | return shared_ptr<_Tp>(__r, __const_cast_tag()); | |
730 | } | |
731 | ||
732 | /** @warning The seemingly equivalent | |
733 | * <code>shared_ptr<T>(dynamic_cast<T*>(r.get()))</code> | |
734 | * will eventually result in undefined behaviour, | |
735 | * attempting to delete the same object twice. | |
736 | */ | |
81809516 | 737 | template<typename _Tp, typename _Tp1> |
b758b22a BK |
738 | shared_ptr<_Tp> |
739 | dynamic_pointer_cast(const shared_ptr<_Tp1>& __r) | |
740 | { | |
741 | return shared_ptr<_Tp>(__r, __dynamic_cast_tag()); | |
742 | } | |
743 | ||
27473454 | 744 | // 2.2.3.7 shared_ptr I/O |
81809516 | 745 | template<typename _Ch, typename _Tr, typename _Tp> |
27473454 PC |
746 | std::basic_ostream<_Ch, _Tr>& |
747 | operator<<(std::basic_ostream<_Ch, _Tr>& __os, const shared_ptr<_Tp>& __p) | |
b758b22a BK |
748 | { |
749 | __os << __p.get(); | |
750 | return __os; | |
751 | } | |
752 | ||
27473454 | 753 | // 2.2.3.10 shared_ptr get_deleter (experimental) |
81809516 | 754 | template<typename _Del, typename _Tp> |
27473454 PC |
755 | inline _Del* |
756 | get_deleter(const shared_ptr<_Tp>& __p) | |
757 | { return static_cast<_Del*>(__p._M_get_deleter(typeid(_Del))); } | |
758 | ||
b758b22a | 759 | |
81809516 | 760 | template<typename _Tp> |
b758b22a BK |
761 | class weak_ptr |
762 | { | |
763 | public: | |
764 | ||
765 | typedef _Tp element_type; | |
766 | ||
767 | weak_ptr() | |
768 | : _M_ptr(0), _M_refcount() // never throws | |
769 | { } | |
770 | ||
81809516 PC |
771 | // generated copy constructor, assignment, destructor are fine |
772 | ||
773 | // | |
774 | // The "obvious" converting constructor implementation: | |
775 | // | |
776 | // template<class Y> | |
777 | // weak_ptr(weak_ptr<Y> const & r) | |
778 | // : _M_ptr(r._M_ptr), _M_refcount(r._M_refcount) // never throws | |
779 | // { } | |
780 | // | |
781 | // has a serious problem. | |
782 | // | |
783 | // r._M_ptr may already have been invalidated. The _M_ptr(r._M_ptr) | |
784 | // conversion may require access to *r._M_ptr (virtual inheritance). | |
785 | // | |
786 | // It is not possible to avoid spurious access violations since | |
787 | // in multithreaded programs r._M_ptr may be invalidated at any point. | |
788 | // | |
789 | ||
790 | template<typename _Tp1> | |
b758b22a BK |
791 | weak_ptr(const weak_ptr<_Tp1>& r) |
792 | : _M_refcount(r._M_refcount) // never throws | |
793 | { | |
794 | __glibcxx_function_requires(_ConvertibleConcept<_Tp1*, _Tp*>) | |
795 | _M_ptr = r.lock().get(); | |
796 | } | |
797 | ||
81809516 | 798 | template<typename _Tp1> |
b758b22a BK |
799 | weak_ptr(const shared_ptr<_Tp1>& r) |
800 | : _M_ptr(r._M_ptr), _M_refcount(r._M_refcount) // never throws | |
801 | { | |
802 | __glibcxx_function_requires(_ConvertibleConcept<_Tp1*, _Tp*>) | |
803 | } | |
804 | ||
81809516 | 805 | template<typename _Tp1> |
b758b22a BK |
806 | weak_ptr& |
807 | operator=(const weak_ptr<_Tp1>& r) // never throws | |
808 | { | |
809 | _M_ptr = r.lock().get(); | |
810 | _M_refcount = r._M_refcount; | |
811 | return *this; | |
812 | } | |
813 | ||
81809516 | 814 | template<typename _Tp1> |
b758b22a BK |
815 | weak_ptr& |
816 | operator=(const shared_ptr<_Tp1>& r) // never throws | |
817 | { | |
818 | _M_ptr = r._M_ptr; | |
819 | _M_refcount = r._M_refcount; | |
820 | return *this; | |
821 | } | |
822 | ||
823 | shared_ptr<_Tp> | |
824 | lock() const // never throws | |
825 | { | |
826 | #ifdef __GTHREADS | |
827 | ||
828 | // optimization: avoid throw overhead | |
829 | if (expired()) | |
81809516 PC |
830 | return shared_ptr<element_type>(); |
831 | ||
b758b22a | 832 | try |
81809516 PC |
833 | { |
834 | return shared_ptr<element_type>(*this); | |
835 | } | |
b758b22a | 836 | catch (const bad_weak_ptr&) |
81809516 PC |
837 | { |
838 | // Q: how can we get here? | |
839 | // A: another thread may have invalidated r after the | |
840 | // use_count test above. | |
841 | return shared_ptr<element_type>(); | |
842 | } | |
b758b22a BK |
843 | |
844 | #else | |
845 | ||
846 | // optimization: avoid try/catch overhead when single threaded | |
81809516 PC |
847 | return expired() ? shared_ptr<element_type>() |
848 | : shared_ptr<element_type>(*this); | |
b758b22a BK |
849 | |
850 | #endif | |
851 | } // XXX MT | |
852 | ||
853 | ||
854 | long | |
855 | use_count() const // never throws | |
856 | { return _M_refcount.use_count(); } | |
857 | ||
858 | bool | |
859 | expired() const // never throws | |
860 | { return _M_refcount.use_count() == 0; } | |
861 | ||
862 | void | |
863 | reset() // never throws | |
864 | { weak_ptr().swap(*this); } | |
865 | ||
866 | void | |
867 | swap(weak_ptr& __s) // never throws | |
868 | { | |
869 | std::swap(_M_ptr, __s._M_ptr); | |
870 | _M_refcount.swap(__s._M_refcount); | |
871 | } | |
872 | ||
873 | private: | |
874 | ||
81809516 | 875 | template<typename _Tp1> |
b758b22a BK |
876 | bool |
877 | _M_less(const weak_ptr<_Tp1>& __rhs) const | |
878 | { return _M_refcount < __rhs._M_refcount; } | |
879 | ||
880 | // used by __enable_shared_from_this | |
881 | void | |
882 | _M_assign(_Tp* __ptr, const shared_count& __refcount) | |
883 | { | |
884 | _M_ptr = __ptr; | |
885 | _M_refcount = __refcount; | |
886 | } | |
887 | ||
888 | // friend injected into namespace and found by ADL | |
889 | ||
81809516 | 890 | template<typename _Tp1> |
b758b22a BK |
891 | friend inline bool |
892 | operator<(const weak_ptr& __lhs, const weak_ptr<_Tp1>& __rhs) | |
893 | { return __lhs._M_less(__rhs); } | |
894 | ||
81809516 PC |
895 | template<typename _Tp1> friend class weak_ptr; |
896 | template<typename _Tp1> friend class shared_ptr; | |
b758b22a BK |
897 | friend class enable_shared_from_this<_Tp>; |
898 | ||
899 | _Tp* _M_ptr; // contained pointer | |
900 | weak_count _M_refcount; // reference counter | |
901 | ||
902 | }; // weak_ptr | |
903 | ||
904 | ||
81809516 | 905 | template<typename _Tp> |
b758b22a BK |
906 | class enable_shared_from_this |
907 | { | |
908 | protected: | |
909 | ||
910 | enable_shared_from_this() | |
911 | { } | |
912 | ||
913 | enable_shared_from_this(const enable_shared_from_this&) | |
914 | { } | |
915 | ||
916 | enable_shared_from_this& | |
917 | operator=(const enable_shared_from_this&) | |
918 | { return *this; } | |
919 | ||
920 | ~enable_shared_from_this() | |
921 | { } | |
922 | ||
923 | public: | |
924 | ||
925 | shared_ptr<_Tp> | |
926 | shared_from_this() | |
927 | { | |
81809516 PC |
928 | shared_ptr<_Tp> __p(this->_M_weak_this); |
929 | return __p; | |
b758b22a BK |
930 | } |
931 | ||
932 | shared_ptr<const _Tp> | |
933 | shared_from_this() const | |
934 | { | |
81809516 PC |
935 | shared_ptr<const _Tp> __p(this->_M_weak_this); |
936 | return __p; | |
b758b22a BK |
937 | } |
938 | ||
939 | private: | |
81809516 | 940 | template<typename _Tp1> |
b758b22a BK |
941 | void |
942 | _M_weak_assign(_Tp1* __p, const shared_count& __n) const | |
943 | { _M_weak_this._M_assign(__p, __n); } | |
944 | ||
81809516 | 945 | template<typename _Tp1> |
b758b22a | 946 | friend void |
81809516 PC |
947 | __enable_shared_from_this(const shared_count& __pn, |
948 | const enable_shared_from_this* __pe, | |
949 | const _Tp1* __px) | |
b758b22a BK |
950 | { |
951 | if(__pe != 0) | |
952 | __pe->_M_weak_assign(const_cast<_Tp1*>(__px), __pn); | |
953 | } | |
954 | ||
955 | mutable weak_ptr<_Tp> _M_weak_this; | |
956 | }; | |
957 | ||
958 | } // namespace tr1 | |
959 | ||
960 | /** | |
961 | * @brief std::swap() specialisation for shared_ptr. | |
962 | * @relates shared_ptr. | |
963 | */ | |
81809516 | 964 | template<typename _Tp> |
b758b22a BK |
965 | inline void |
966 | swap(tr1::shared_ptr<_Tp>& __a, tr1::shared_ptr<_Tp>& __b) | |
967 | { | |
968 | __a.swap(__b); | |
969 | } | |
970 | ||
971 | /** | |
972 | * @brief std::swap() specialisation for weak_ptr. | |
973 | * @relates weak_ptr. | |
974 | */ | |
81809516 | 975 | template<typename _Tp> |
b758b22a BK |
976 | void |
977 | swap(tr1::weak_ptr<_Tp>& __a, tr1::weak_ptr<_Tp>& __b) | |
978 | { | |
979 | __a.swap(__b); | |
980 | } | |
981 | ||
982 | } // namespace std | |
983 | ||
984 | #endif |