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