OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [libstdc++-v3/] [include/] [tr1/] [shared_ptr.h] - Blame information for rev 747

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 742 jeremybenn
// <tr1/shared_ptr.h> -*- C++ -*-
2
 
3
// Copyright (C) 2007, 2008, 2009, 2010, 2011, 2012
4
// Free Software Foundation, Inc.
5
//
6
// This file is part of the GNU ISO C++ Library.  This library is free
7
// software; you can redistribute it and/or modify it under the
8
// terms of the GNU General Public License as published by the
9
// Free Software Foundation; either version 3, or (at your option)
10
// any later version.
11
 
12
// This library is distributed in the hope that it will be useful,
13
// but WITHOUT ANY WARRANTY; without even the implied warranty of
14
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
// GNU General Public License for more details.
16
 
17
// Under Section 7 of GPL version 3, you are granted additional
18
// permissions described in the GCC Runtime Library Exception, version
19
// 3.1, as published by the Free Software Foundation.
20
 
21
// You should have received a copy of the GNU General Public License and
22
// a copy of the GCC Runtime Library Exception along with this program;
23
// see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
24
// <http://www.gnu.org/licenses/>.
25
 
26
//  shared_count.hpp
27
//  Copyright (c) 2001, 2002, 2003 Peter Dimov and Multi Media Ltd.
28
 
29
//  shared_ptr.hpp
30
//  Copyright (C) 1998, 1999 Greg Colvin and Beman Dawes.
31
//  Copyright (C) 2001, 2002, 2003 Peter Dimov
32
 
33
//  weak_ptr.hpp
34
//  Copyright (C) 2001, 2002, 2003 Peter Dimov
35
 
36
//  enable_shared_from_this.hpp
37
//  Copyright (C) 2002 Peter Dimov
38
 
39
// Distributed under the Boost Software License, Version 1.0. (See
40
// accompanying file LICENSE_1_0.txt or copy at
41
// http://www.boost.org/LICENSE_1_0.txt)
42
 
43
// GCC Note:  based on version 1.32.0 of the Boost library.
44
 
45
/** @file tr1/shared_ptr.h
46
 *  This is an internal header file, included by other library headers.
47
 *  Do not attempt to use it directly. @headername{tr1/memory}
48
 */
49
 
50
#ifndef _TR1_SHARED_PTR_H
51
#define _TR1_SHARED_PTR_H 1
52
 
53
namespace std _GLIBCXX_VISIBILITY(default)
54
{
55
namespace tr1
56
{
57
_GLIBCXX_BEGIN_NAMESPACE_VERSION
58
 
59
 /**
60
   *  @brief  Exception possibly thrown by @c shared_ptr.
61
   *  @ingroup exceptions
62
   */
63
  class bad_weak_ptr : public std::exception
64
  {
65
  public:
66
    virtual char const*
67
    what() const throw()
68
    { return "tr1::bad_weak_ptr"; }
69
  };
70
 
71
  // Substitute for bad_weak_ptr object in the case of -fno-exceptions.
72
  inline void
73
  __throw_bad_weak_ptr()
74
  {
75
#if __EXCEPTIONS
76
    throw bad_weak_ptr();
77
#else
78
    __builtin_abort();
79
#endif
80
  }
81
 
82
  using __gnu_cxx::_Lock_policy;
83
  using __gnu_cxx::__default_lock_policy;
84
  using __gnu_cxx::_S_single;
85
  using __gnu_cxx::_S_mutex;
86
  using __gnu_cxx::_S_atomic;
87
 
88
  // Empty helper class except when the template argument is _S_mutex.
89
  template<_Lock_policy _Lp>
90
    class _Mutex_base
91
    {
92
    protected:
93
      // The atomic policy uses fully-fenced builtins, single doesn't care.
94
      enum { _S_need_barriers = 0 };
95
    };
96
 
97
  template<>
98
    class _Mutex_base<_S_mutex>
99
    : public __gnu_cxx::__mutex
100
    {
101
    protected:
102
      // This policy is used when atomic builtins are not available.
103
      // The replacement atomic operations might not have the necessary
104
      // memory barriers.
105
      enum { _S_need_barriers = 1 };
106
    };
107
 
108
  template<_Lock_policy _Lp = __default_lock_policy>
109
    class _Sp_counted_base
110
    : public _Mutex_base<_Lp>
111
    {
112
    public:
113
      _Sp_counted_base()
114
      : _M_use_count(1), _M_weak_count(1) { }
115
 
116
      virtual
117
      ~_Sp_counted_base() // nothrow 
118
      { }
119
 
120
      // Called when _M_use_count drops to zero, to release the resources
121
      // managed by *this.
122
      virtual void
123
      _M_dispose() = 0; // nothrow
124
 
125
      // Called when _M_weak_count drops to zero.
126
      virtual void
127
      _M_destroy() // nothrow
128
      { delete this; }
129
 
130
      virtual void*
131
      _M_get_deleter(const std::type_info&) = 0;
132
 
133
      void
134
      _M_add_ref_copy()
135
      { __gnu_cxx::__atomic_add_dispatch(&_M_use_count, 1); }
136
 
137
      void
138
      _M_add_ref_lock();
139
 
140
      void
141
      _M_release() // nothrow
142
      {
143
        // Be race-detector-friendly.  For more info see bits/c++config.
144
        _GLIBCXX_SYNCHRONIZATION_HAPPENS_BEFORE(&_M_use_count);
145
        if (__gnu_cxx::__exchange_and_add_dispatch(&_M_use_count, -1) == 1)
146
          {
147
            _GLIBCXX_SYNCHRONIZATION_HAPPENS_AFTER(&_M_use_count);
148
            _M_dispose();
149
            // There must be a memory barrier between dispose() and destroy()
150
            // to ensure that the effects of dispose() are observed in the
151
            // thread that runs destroy().
152
            // See http://gcc.gnu.org/ml/libstdc++/2005-11/msg00136.html
153
            if (_Mutex_base<_Lp>::_S_need_barriers)
154
              {
155
                _GLIBCXX_READ_MEM_BARRIER;
156
                _GLIBCXX_WRITE_MEM_BARRIER;
157
              }
158
 
159
            // Be race-detector-friendly.  For more info see bits/c++config.
160
            _GLIBCXX_SYNCHRONIZATION_HAPPENS_BEFORE(&_M_weak_count);
161
            if (__gnu_cxx::__exchange_and_add_dispatch(&_M_weak_count,
162
                                                       -1) == 1)
163
              {
164
                _GLIBCXX_SYNCHRONIZATION_HAPPENS_AFTER(&_M_weak_count);
165
                _M_destroy();
166
              }
167
          }
168
      }
169
 
170
      void
171
      _M_weak_add_ref() // nothrow
172
      { __gnu_cxx::__atomic_add_dispatch(&_M_weak_count, 1); }
173
 
174
      void
175
      _M_weak_release() // nothrow
176
      {
177
        // Be race-detector-friendly. For more info see bits/c++config.
178
        _GLIBCXX_SYNCHRONIZATION_HAPPENS_BEFORE(&_M_weak_count);
179
        if (__gnu_cxx::__exchange_and_add_dispatch(&_M_weak_count, -1) == 1)
180
          {
181
            _GLIBCXX_SYNCHRONIZATION_HAPPENS_AFTER(&_M_weak_count);
182
            if (_Mutex_base<_Lp>::_S_need_barriers)
183
              {
184
                // See _M_release(),
185
                // destroy() must observe results of dispose()
186
                _GLIBCXX_READ_MEM_BARRIER;
187
                _GLIBCXX_WRITE_MEM_BARRIER;
188
              }
189
            _M_destroy();
190
          }
191
      }
192
 
193
      long
194
      _M_get_use_count() const // nothrow
195
      {
196
        // No memory barrier is used here so there is no synchronization
197
        // with other threads.
198
        return const_cast<const volatile _Atomic_word&>(_M_use_count);
199
      }
200
 
201
    private:
202
      _Sp_counted_base(_Sp_counted_base const&);
203
      _Sp_counted_base& operator=(_Sp_counted_base const&);
204
 
205
      _Atomic_word  _M_use_count;     // #shared
206
      _Atomic_word  _M_weak_count;    // #weak + (#shared != 0)
207
    };
208
 
209
  template<>
210
    inline void
211
    _Sp_counted_base<_S_single>::
212
    _M_add_ref_lock()
213
    {
214
      if (__gnu_cxx::__exchange_and_add_dispatch(&_M_use_count, 1) == 0)
215
        {
216
          _M_use_count = 0;
217
          __throw_bad_weak_ptr();
218
        }
219
    }
220
 
221
  template<>
222
    inline void
223
    _Sp_counted_base<_S_mutex>::
224
    _M_add_ref_lock()
225
    {
226
      __gnu_cxx::__scoped_lock sentry(*this);
227
      if (__gnu_cxx::__exchange_and_add_dispatch(&_M_use_count, 1) == 0)
228
        {
229
          _M_use_count = 0;
230
          __throw_bad_weak_ptr();
231
        }
232
    }
233
 
234
  template<>
235
    inline void
236
    _Sp_counted_base<_S_atomic>::
237
    _M_add_ref_lock()
238
    {
239
      // Perform lock-free add-if-not-zero operation.
240
      _Atomic_word __count = _M_use_count;
241
      do
242
        {
243
          if (__count == 0)
244
            __throw_bad_weak_ptr();
245
          // Replace the current counter value with the old value + 1, as
246
          // long as it's not changed meanwhile. 
247
        }
248
      while (!__atomic_compare_exchange_n(&_M_use_count, &__count, __count + 1,
249
                                          true, __ATOMIC_ACQ_REL,
250
                                          __ATOMIC_RELAXED));
251
     }
252
 
253
  template<typename _Ptr, typename _Deleter, _Lock_policy _Lp>
254
    class _Sp_counted_base_impl
255
    : public _Sp_counted_base<_Lp>
256
    {
257
    public:
258
      // Precondition: __d(__p) must not throw.
259
      _Sp_counted_base_impl(_Ptr __p, _Deleter __d)
260
      : _M_ptr(__p), _M_del(__d) { }
261
 
262
      virtual void
263
      _M_dispose() // nothrow
264
      { _M_del(_M_ptr); }
265
 
266
      virtual void*
267
      _M_get_deleter(const std::type_info& __ti)
268
      {
269
#ifdef __GXX_RTTI
270
        return __ti == typeid(_Deleter) ? &_M_del : 0;
271
#else
272
        return 0;
273
#endif
274
      }
275
 
276
    private:
277
      _Sp_counted_base_impl(const _Sp_counted_base_impl&);
278
      _Sp_counted_base_impl& operator=(const _Sp_counted_base_impl&);
279
 
280
      _Ptr      _M_ptr;  // copy constructor must not throw
281
      _Deleter  _M_del;  // copy constructor must not throw
282
    };
283
 
284
  template<_Lock_policy _Lp = __default_lock_policy>
285
    class __weak_count;
286
 
287
  template<typename _Tp>
288
    struct _Sp_deleter
289
    {
290
      typedef void result_type;
291
      typedef _Tp* argument_type;
292
      void operator()(_Tp* __p) const { delete __p; }
293
    };
294
 
295
  template<_Lock_policy _Lp = __default_lock_policy>
296
    class __shared_count
297
    {
298
    public:
299
      __shared_count()
300
      : _M_pi(0) // nothrow
301
      { }
302
 
303
      template<typename _Ptr>
304
        __shared_count(_Ptr __p) : _M_pi(0)
305
        {
306
          __try
307
            {
308
              typedef typename std::tr1::remove_pointer<_Ptr>::type _Tp;
309
              _M_pi = new _Sp_counted_base_impl<_Ptr, _Sp_deleter<_Tp>, _Lp>(
310
                  __p, _Sp_deleter<_Tp>());
311
            }
312
          __catch(...)
313
            {
314
              delete __p;
315
              __throw_exception_again;
316
            }
317
        }
318
 
319
      template<typename _Ptr, typename _Deleter>
320
        __shared_count(_Ptr __p, _Deleter __d) : _M_pi(0)
321
        {
322
          __try
323
            {
324
              _M_pi = new _Sp_counted_base_impl<_Ptr, _Deleter, _Lp>(__p, __d);
325
            }
326
          __catch(...)
327
            {
328
              __d(__p); // Call _Deleter on __p.
329
              __throw_exception_again;
330
            }
331
        }
332
 
333
      // Special case for auto_ptr<_Tp> to provide the strong guarantee.
334
      template<typename _Tp>
335
        explicit
336
        __shared_count(std::auto_ptr<_Tp>& __r)
337
        : _M_pi(new _Sp_counted_base_impl<_Tp*,
338
                _Sp_deleter<_Tp>, _Lp >(__r.get(), _Sp_deleter<_Tp>()))
339
        { __r.release(); }
340
 
341
      // Throw bad_weak_ptr when __r._M_get_use_count() == 0.
342
      explicit
343
      __shared_count(const __weak_count<_Lp>& __r);
344
 
345
      ~__shared_count() // nothrow
346
      {
347
        if (_M_pi != 0)
348
          _M_pi->_M_release();
349
      }
350
 
351
      __shared_count(const __shared_count& __r)
352
      : _M_pi(__r._M_pi) // nothrow
353
      {
354
        if (_M_pi != 0)
355
          _M_pi->_M_add_ref_copy();
356
      }
357
 
358
      __shared_count&
359
      operator=(const __shared_count& __r) // nothrow
360
      {
361
        _Sp_counted_base<_Lp>* __tmp = __r._M_pi;
362
        if (__tmp != _M_pi)
363
          {
364
            if (__tmp != 0)
365
              __tmp->_M_add_ref_copy();
366
            if (_M_pi != 0)
367
              _M_pi->_M_release();
368
            _M_pi = __tmp;
369
          }
370
        return *this;
371
      }
372
 
373
      void
374
      _M_swap(__shared_count& __r) // nothrow
375
      {
376
        _Sp_counted_base<_Lp>* __tmp = __r._M_pi;
377
        __r._M_pi = _M_pi;
378
        _M_pi = __tmp;
379
      }
380
 
381
      long
382
      _M_get_use_count() const // nothrow
383
      { return _M_pi != 0 ? _M_pi->_M_get_use_count() : 0; }
384
 
385
      bool
386
      _M_unique() const // nothrow
387
      { return this->_M_get_use_count() == 1; }
388
 
389
      friend inline bool
390
      operator==(const __shared_count& __a, const __shared_count& __b)
391
      { return __a._M_pi == __b._M_pi; }
392
 
393
      friend inline bool
394
      operator<(const __shared_count& __a, const __shared_count& __b)
395
      { return std::less<_Sp_counted_base<_Lp>*>()(__a._M_pi, __b._M_pi); }
396
 
397
      void*
398
      _M_get_deleter(const std::type_info& __ti) const
399
      { return _M_pi ? _M_pi->_M_get_deleter(__ti) : 0; }
400
 
401
    private:
402
      friend class __weak_count<_Lp>;
403
 
404
      _Sp_counted_base<_Lp>*  _M_pi;
405
    };
406
 
407
 
408
  template<_Lock_policy _Lp>
409
    class __weak_count
410
    {
411
    public:
412
      __weak_count()
413
      : _M_pi(0) // nothrow
414
      { }
415
 
416
      __weak_count(const __shared_count<_Lp>& __r)
417
      : _M_pi(__r._M_pi) // nothrow
418
      {
419
        if (_M_pi != 0)
420
          _M_pi->_M_weak_add_ref();
421
      }
422
 
423
      __weak_count(const __weak_count<_Lp>& __r)
424
      : _M_pi(__r._M_pi) // nothrow
425
      {
426
        if (_M_pi != 0)
427
          _M_pi->_M_weak_add_ref();
428
      }
429
 
430
      ~__weak_count() // nothrow
431
      {
432
        if (_M_pi != 0)
433
          _M_pi->_M_weak_release();
434
      }
435
 
436
      __weak_count<_Lp>&
437
      operator=(const __shared_count<_Lp>& __r) // nothrow
438
      {
439
        _Sp_counted_base<_Lp>* __tmp = __r._M_pi;
440
        if (__tmp != 0)
441
          __tmp->_M_weak_add_ref();
442
        if (_M_pi != 0)
443
          _M_pi->_M_weak_release();
444
        _M_pi = __tmp;
445
        return *this;
446
      }
447
 
448
      __weak_count<_Lp>&
449
      operator=(const __weak_count<_Lp>& __r) // nothrow
450
      {
451
        _Sp_counted_base<_Lp>* __tmp = __r._M_pi;
452
        if (__tmp != 0)
453
          __tmp->_M_weak_add_ref();
454
        if (_M_pi != 0)
455
          _M_pi->_M_weak_release();
456
        _M_pi = __tmp;
457
        return *this;
458
      }
459
 
460
      void
461
      _M_swap(__weak_count<_Lp>& __r) // nothrow
462
      {
463
        _Sp_counted_base<_Lp>* __tmp = __r._M_pi;
464
        __r._M_pi = _M_pi;
465
        _M_pi = __tmp;
466
      }
467
 
468
      long
469
      _M_get_use_count() const // nothrow
470
      { return _M_pi != 0 ? _M_pi->_M_get_use_count() : 0; }
471
 
472
      friend inline bool
473
      operator==(const __weak_count<_Lp>& __a, const __weak_count<_Lp>& __b)
474
      { return __a._M_pi == __b._M_pi; }
475
 
476
      friend inline bool
477
      operator<(const __weak_count<_Lp>& __a, const __weak_count<_Lp>& __b)
478
      { return std::less<_Sp_counted_base<_Lp>*>()(__a._M_pi, __b._M_pi); }
479
 
480
    private:
481
      friend class __shared_count<_Lp>;
482
 
483
      _Sp_counted_base<_Lp>*  _M_pi;
484
    };
485
 
486
  // now that __weak_count is defined we can define this constructor:
487
  template<_Lock_policy _Lp>
488
    inline
489
    __shared_count<_Lp>::
490
    __shared_count(const __weak_count<_Lp>& __r)
491
    : _M_pi(__r._M_pi)
492
    {
493
      if (_M_pi != 0)
494
        _M_pi->_M_add_ref_lock();
495
      else
496
        __throw_bad_weak_ptr();
497
    }
498
 
499
  // Forward declarations.
500
  template<typename _Tp, _Lock_policy _Lp = __default_lock_policy>
501
    class __shared_ptr;
502
 
503
  template<typename _Tp, _Lock_policy _Lp = __default_lock_policy>
504
    class __weak_ptr;
505
 
506
  template<typename _Tp, _Lock_policy _Lp = __default_lock_policy>
507
    class __enable_shared_from_this;
508
 
509
  template<typename _Tp>
510
    class shared_ptr;
511
 
512
  template<typename _Tp>
513
    class weak_ptr;
514
 
515
  template<typename _Tp>
516
    class enable_shared_from_this;
517
 
518
  // Support for enable_shared_from_this.
519
 
520
  // Friend of __enable_shared_from_this.
521
  template<_Lock_policy _Lp, typename _Tp1, typename _Tp2>
522
    void
523
    __enable_shared_from_this_helper(const __shared_count<_Lp>&,
524
                                     const __enable_shared_from_this<_Tp1,
525
                                     _Lp>*, const _Tp2*);
526
 
527
  // Friend of enable_shared_from_this.
528
  template<typename _Tp1, typename _Tp2>
529
    void
530
    __enable_shared_from_this_helper(const __shared_count<>&,
531
                                     const enable_shared_from_this<_Tp1>*,
532
                                     const _Tp2*);
533
 
534
  template<_Lock_policy _Lp>
535
    inline void
536
    __enable_shared_from_this_helper(const __shared_count<_Lp>&, ...)
537
    { }
538
 
539
 
540
  struct __static_cast_tag { };
541
  struct __const_cast_tag { };
542
  struct __dynamic_cast_tag { };
543
 
544
  // A smart pointer with reference-counted copy semantics.  The
545
  // object pointed to is deleted when the last shared_ptr pointing to
546
  // it is destroyed or reset.
547
  template<typename _Tp, _Lock_policy _Lp>
548
    class __shared_ptr
549
    {
550
    public:
551
      typedef _Tp   element_type;
552
 
553
      __shared_ptr()
554
      : _M_ptr(0), _M_refcount() // never throws
555
      { }
556
 
557
      template<typename _Tp1>
558
        explicit
559
        __shared_ptr(_Tp1* __p)
560
        : _M_ptr(__p), _M_refcount(__p)
561
        {
562
          __glibcxx_function_requires(_ConvertibleConcept<_Tp1*, _Tp*>)
563
          typedef int _IsComplete[sizeof(_Tp1)];
564
          __enable_shared_from_this_helper(_M_refcount, __p, __p);
565
        }
566
 
567
      template<typename _Tp1, typename _Deleter>
568
        __shared_ptr(_Tp1* __p, _Deleter __d)
569
        : _M_ptr(__p), _M_refcount(__p, __d)
570
        {
571
          __glibcxx_function_requires(_ConvertibleConcept<_Tp1*, _Tp*>)
572
          // TODO requires _Deleter CopyConstructible and __d(__p) well-formed
573
          __enable_shared_from_this_helper(_M_refcount, __p, __p);
574
        }
575
 
576
      //  generated copy constructor, assignment, destructor are fine.
577
 
578
      template<typename _Tp1>
579
        __shared_ptr(const __shared_ptr<_Tp1, _Lp>& __r)
580
        : _M_ptr(__r._M_ptr), _M_refcount(__r._M_refcount) // never throws
581
        { __glibcxx_function_requires(_ConvertibleConcept<_Tp1*, _Tp*>) }
582
 
583
      template<typename _Tp1>
584
        explicit
585
        __shared_ptr(const __weak_ptr<_Tp1, _Lp>& __r)
586
        : _M_refcount(__r._M_refcount) // may throw
587
        {
588
          __glibcxx_function_requires(_ConvertibleConcept<_Tp1*, _Tp*>)
589
          // It is now safe to copy __r._M_ptr, as _M_refcount(__r._M_refcount)
590
          // did not throw.
591
          _M_ptr = __r._M_ptr;
592
        }
593
 
594
#if !defined(__GXX_EXPERIMENTAL_CXX0X__) || _GLIBCXX_USE_DEPRECATED
595
      // Postcondition: use_count() == 1 and __r.get() == 0
596
      template<typename _Tp1>
597
        explicit
598
        __shared_ptr(std::auto_ptr<_Tp1>& __r)
599
        : _M_ptr(__r.get()), _M_refcount()
600
        { // TODO requries delete __r.release() well-formed
601
          __glibcxx_function_requires(_ConvertibleConcept<_Tp1*, _Tp*>)
602
          typedef int _IsComplete[sizeof(_Tp1)];
603
          _Tp1* __tmp = __r.get();
604
          _M_refcount = __shared_count<_Lp>(__r);
605
          __enable_shared_from_this_helper(_M_refcount, __tmp, __tmp);
606
        }
607
 
608
#endif
609
 
610
      template<typename _Tp1>
611
        __shared_ptr(const __shared_ptr<_Tp1, _Lp>& __r, __static_cast_tag)
612
        : _M_ptr(static_cast<element_type*>(__r._M_ptr)),
613
          _M_refcount(__r._M_refcount)
614
        { }
615
 
616
      template<typename _Tp1>
617
        __shared_ptr(const __shared_ptr<_Tp1, _Lp>& __r, __const_cast_tag)
618
        : _M_ptr(const_cast<element_type*>(__r._M_ptr)),
619
          _M_refcount(__r._M_refcount)
620
        { }
621
 
622
      template<typename _Tp1>
623
        __shared_ptr(const __shared_ptr<_Tp1, _Lp>& __r, __dynamic_cast_tag)
624
        : _M_ptr(dynamic_cast<element_type*>(__r._M_ptr)),
625
          _M_refcount(__r._M_refcount)
626
        {
627
          if (_M_ptr == 0) // need to allocate new counter -- the cast failed
628
            _M_refcount = __shared_count<_Lp>();
629
        }
630
 
631
      template<typename _Tp1>
632
        __shared_ptr&
633
        operator=(const __shared_ptr<_Tp1, _Lp>& __r) // never throws
634
        {
635
          _M_ptr = __r._M_ptr;
636
          _M_refcount = __r._M_refcount; // __shared_count::op= doesn't throw
637
          return *this;
638
        }
639
 
640
#if !defined(__GXX_EXPERIMENTAL_CXX0X__) || _GLIBCXX_USE_DEPRECATED
641
      template<typename _Tp1>
642
        __shared_ptr&
643
        operator=(std::auto_ptr<_Tp1>& __r)
644
        {
645
          __shared_ptr(__r).swap(*this);
646
          return *this;
647
        }
648
#endif
649
 
650
      void
651
      reset() // never throws
652
      { __shared_ptr().swap(*this); }
653
 
654
      template<typename _Tp1>
655
        void
656
        reset(_Tp1* __p) // _Tp1 must be complete.
657
        {
658
          // Catch self-reset errors.
659
          _GLIBCXX_DEBUG_ASSERT(__p == 0 || __p != _M_ptr);
660
          __shared_ptr(__p).swap(*this);
661
        }
662
 
663
      template<typename _Tp1, typename _Deleter>
664
        void
665
        reset(_Tp1* __p, _Deleter __d)
666
        { __shared_ptr(__p, __d).swap(*this); }
667
 
668
      // Allow class instantiation when _Tp is [cv-qual] void.
669
      typename std::tr1::add_reference<_Tp>::type
670
      operator*() const // never throws
671
      {
672
        _GLIBCXX_DEBUG_ASSERT(_M_ptr != 0);
673
        return *_M_ptr;
674
      }
675
 
676
      _Tp*
677
      operator->() const // never throws
678
      {
679
        _GLIBCXX_DEBUG_ASSERT(_M_ptr != 0);
680
        return _M_ptr;
681
      }
682
 
683
      _Tp*
684
      get() const // never throws
685
      { return _M_ptr; }
686
 
687
      // Implicit conversion to "bool"
688
    private:
689
      typedef _Tp* __shared_ptr::*__unspecified_bool_type;
690
 
691
    public:
692
      operator __unspecified_bool_type() const // never throws
693
      { return _M_ptr == 0 ? 0 : &__shared_ptr::_M_ptr; }
694
 
695
      bool
696
      unique() const // never throws
697
      { return _M_refcount._M_unique(); }
698
 
699
      long
700
      use_count() const // never throws
701
      { return _M_refcount._M_get_use_count(); }
702
 
703
      void
704
      swap(__shared_ptr<_Tp, _Lp>& __other) // never throws
705
      {
706
        std::swap(_M_ptr, __other._M_ptr);
707
        _M_refcount._M_swap(__other._M_refcount);
708
      }
709
 
710
    private:
711
      void*
712
      _M_get_deleter(const std::type_info& __ti) const
713
      { return _M_refcount._M_get_deleter(__ti); }
714
 
715
      template<typename _Tp1, _Lock_policy _Lp1>
716
        bool
717
        _M_less(const __shared_ptr<_Tp1, _Lp1>& __rhs) const
718
        { return _M_refcount < __rhs._M_refcount; }
719
 
720
      template<typename _Tp1, _Lock_policy _Lp1> friend class __shared_ptr;
721
      template<typename _Tp1, _Lock_policy _Lp1> friend class __weak_ptr;
722
 
723
      template<typename _Del, typename _Tp1, _Lock_policy _Lp1>
724
        friend _Del* get_deleter(const __shared_ptr<_Tp1, _Lp1>&);
725
 
726
      // Friends injected into enclosing namespace and found by ADL:
727
      template<typename _Tp1>
728
        friend inline bool
729
        operator==(const __shared_ptr& __a, const __shared_ptr<_Tp1, _Lp>& __b)
730
        { return __a.get() == __b.get(); }
731
 
732
      template<typename _Tp1>
733
        friend inline bool
734
        operator!=(const __shared_ptr& __a, const __shared_ptr<_Tp1, _Lp>& __b)
735
        { return __a.get() != __b.get(); }
736
 
737
      template<typename _Tp1>
738
        friend inline bool
739
        operator<(const __shared_ptr& __a, const __shared_ptr<_Tp1, _Lp>& __b)
740
        { return __a._M_less(__b); }
741
 
742
      _Tp*                 _M_ptr;         // Contained pointer.
743
      __shared_count<_Lp>  _M_refcount;    // Reference counter.
744
    };
745
 
746
  // 2.2.3.8 shared_ptr specialized algorithms.
747
  template<typename _Tp, _Lock_policy _Lp>
748
    inline void
749
    swap(__shared_ptr<_Tp, _Lp>& __a, __shared_ptr<_Tp, _Lp>& __b)
750
    { __a.swap(__b); }
751
 
752
  // 2.2.3.9 shared_ptr casts
753
  /*  The seemingly equivalent
754
   *           shared_ptr<_Tp, _Lp>(static_cast<_Tp*>(__r.get()))
755
   *  will eventually result in undefined behaviour,
756
   *  attempting to delete the same object twice.
757
   */
758
  template<typename _Tp, typename _Tp1, _Lock_policy _Lp>
759
    inline __shared_ptr<_Tp, _Lp>
760
    static_pointer_cast(const __shared_ptr<_Tp1, _Lp>& __r)
761
    { return __shared_ptr<_Tp, _Lp>(__r, __static_cast_tag()); }
762
 
763
  /*  The seemingly equivalent
764
   *           shared_ptr<_Tp, _Lp>(const_cast<_Tp*>(__r.get()))
765
   *  will eventually result in undefined behaviour,
766
   *  attempting to delete the same object twice.
767
   */
768
  template<typename _Tp, typename _Tp1, _Lock_policy _Lp>
769
    inline __shared_ptr<_Tp, _Lp>
770
    const_pointer_cast(const __shared_ptr<_Tp1, _Lp>& __r)
771
    { return __shared_ptr<_Tp, _Lp>(__r, __const_cast_tag()); }
772
 
773
  /*  The seemingly equivalent
774
   *           shared_ptr<_Tp, _Lp>(dynamic_cast<_Tp*>(__r.get()))
775
   *  will eventually result in undefined behaviour,
776
   *  attempting to delete the same object twice.
777
   */
778
  template<typename _Tp, typename _Tp1, _Lock_policy _Lp>
779
    inline __shared_ptr<_Tp, _Lp>
780
    dynamic_pointer_cast(const __shared_ptr<_Tp1, _Lp>& __r)
781
    { return __shared_ptr<_Tp, _Lp>(__r, __dynamic_cast_tag()); }
782
 
783
  // 2.2.3.7 shared_ptr I/O
784
  template<typename _Ch, typename _Tr, typename _Tp, _Lock_policy _Lp>
785
    std::basic_ostream<_Ch, _Tr>&
786
    operator<<(std::basic_ostream<_Ch, _Tr>& __os,
787
               const __shared_ptr<_Tp, _Lp>& __p)
788
    {
789
      __os << __p.get();
790
      return __os;
791
    }
792
 
793
  // 2.2.3.10 shared_ptr get_deleter (experimental)
794
  template<typename _Del, typename _Tp, _Lock_policy _Lp>
795
    inline _Del*
796
    get_deleter(const __shared_ptr<_Tp, _Lp>& __p)
797
    {
798
#ifdef __GXX_RTTI
799
      return static_cast<_Del*>(__p._M_get_deleter(typeid(_Del)));
800
#else
801
      return 0;
802
#endif
803
    }
804
 
805
 
806
  template<typename _Tp, _Lock_policy _Lp>
807
    class __weak_ptr
808
    {
809
    public:
810
      typedef _Tp element_type;
811
 
812
      __weak_ptr()
813
      : _M_ptr(0), _M_refcount() // never throws
814
      { }
815
 
816
      // Generated copy constructor, assignment, destructor are fine.
817
 
818
      // The "obvious" converting constructor implementation:
819
      //
820
      //  template<typename _Tp1>
821
      //    __weak_ptr(const __weak_ptr<_Tp1, _Lp>& __r)
822
      //    : _M_ptr(__r._M_ptr), _M_refcount(__r._M_refcount) // never throws
823
      //    { }
824
      //
825
      // has a serious problem.
826
      //
827
      //  __r._M_ptr may already have been invalidated. The _M_ptr(__r._M_ptr)
828
      //  conversion may require access to *__r._M_ptr (virtual inheritance).
829
      //
830
      // It is not possible to avoid spurious access violations since
831
      // in multithreaded programs __r._M_ptr may be invalidated at any point.
832
      template<typename _Tp1>
833
        __weak_ptr(const __weak_ptr<_Tp1, _Lp>& __r)
834
        : _M_refcount(__r._M_refcount) // never throws
835
        {
836
          __glibcxx_function_requires(_ConvertibleConcept<_Tp1*, _Tp*>)
837
          _M_ptr = __r.lock().get();
838
        }
839
 
840
      template<typename _Tp1>
841
        __weak_ptr(const __shared_ptr<_Tp1, _Lp>& __r)
842
        : _M_ptr(__r._M_ptr), _M_refcount(__r._M_refcount) // never throws
843
        { __glibcxx_function_requires(_ConvertibleConcept<_Tp1*, _Tp*>) }
844
 
845
      template<typename _Tp1>
846
        __weak_ptr&
847
        operator=(const __weak_ptr<_Tp1, _Lp>& __r) // never throws
848
        {
849
          _M_ptr = __r.lock().get();
850
          _M_refcount = __r._M_refcount;
851
          return *this;
852
        }
853
 
854
      template<typename _Tp1>
855
        __weak_ptr&
856
        operator=(const __shared_ptr<_Tp1, _Lp>& __r) // never throws
857
        {
858
          _M_ptr = __r._M_ptr;
859
          _M_refcount = __r._M_refcount;
860
          return *this;
861
        }
862
 
863
      __shared_ptr<_Tp, _Lp>
864
      lock() const // never throws
865
      {
866
#ifdef __GTHREADS
867
        // Optimization: avoid throw overhead.
868
        if (expired())
869
          return __shared_ptr<element_type, _Lp>();
870
 
871
        __try
872
          {
873
            return __shared_ptr<element_type, _Lp>(*this);
874
          }
875
        __catch(const bad_weak_ptr&)
876
          {
877
            // Q: How can we get here?
878
            // A: Another thread may have invalidated r after the
879
            //    use_count test above.
880
            return __shared_ptr<element_type, _Lp>();
881
          }
882
 
883
#else
884
        // Optimization: avoid try/catch overhead when single threaded.
885
        return expired() ? __shared_ptr<element_type, _Lp>()
886
                         : __shared_ptr<element_type, _Lp>(*this);
887
 
888
#endif
889
      } // XXX MT
890
 
891
      long
892
      use_count() const // never throws
893
      { return _M_refcount._M_get_use_count(); }
894
 
895
      bool
896
      expired() const // never throws
897
      { return _M_refcount._M_get_use_count() == 0; }
898
 
899
      void
900
      reset() // never throws
901
      { __weak_ptr().swap(*this); }
902
 
903
      void
904
      swap(__weak_ptr& __s) // never throws
905
      {
906
        std::swap(_M_ptr, __s._M_ptr);
907
        _M_refcount._M_swap(__s._M_refcount);
908
      }
909
 
910
    private:
911
      // Used by __enable_shared_from_this.
912
      void
913
      _M_assign(_Tp* __ptr, const __shared_count<_Lp>& __refcount)
914
      {
915
        _M_ptr = __ptr;
916
        _M_refcount = __refcount;
917
      }
918
 
919
      template<typename _Tp1>
920
        bool
921
        _M_less(const __weak_ptr<_Tp1, _Lp>& __rhs) const
922
        { return _M_refcount < __rhs._M_refcount; }
923
 
924
      template<typename _Tp1, _Lock_policy _Lp1> friend class __shared_ptr;
925
      template<typename _Tp1, _Lock_policy _Lp1> friend class __weak_ptr;
926
      friend class __enable_shared_from_this<_Tp, _Lp>;
927
      friend class enable_shared_from_this<_Tp>;
928
 
929
      // Friend injected into namespace and found by ADL.
930
      template<typename _Tp1>
931
        friend inline bool
932
        operator<(const __weak_ptr& __lhs, const __weak_ptr<_Tp1, _Lp>& __rhs)
933
        { return __lhs._M_less(__rhs); }
934
 
935
      _Tp*               _M_ptr;         // Contained pointer.
936
      __weak_count<_Lp>  _M_refcount;    // Reference counter.
937
    };
938
 
939
  // 2.2.4.7 weak_ptr specialized algorithms.
940
  template<typename _Tp, _Lock_policy _Lp>
941
    inline void
942
    swap(__weak_ptr<_Tp, _Lp>& __a, __weak_ptr<_Tp, _Lp>& __b)
943
    { __a.swap(__b); }
944
 
945
 
946
  template<typename _Tp, _Lock_policy _Lp>
947
    class __enable_shared_from_this
948
    {
949
    protected:
950
      __enable_shared_from_this() { }
951
 
952
      __enable_shared_from_this(const __enable_shared_from_this&) { }
953
 
954
      __enable_shared_from_this&
955
      operator=(const __enable_shared_from_this&)
956
      { return *this; }
957
 
958
      ~__enable_shared_from_this() { }
959
 
960
    public:
961
      __shared_ptr<_Tp, _Lp>
962
      shared_from_this()
963
      { return __shared_ptr<_Tp, _Lp>(this->_M_weak_this); }
964
 
965
      __shared_ptr<const _Tp, _Lp>
966
      shared_from_this() const
967
      { return __shared_ptr<const _Tp, _Lp>(this->_M_weak_this); }
968
 
969
    private:
970
      template<typename _Tp1>
971
        void
972
        _M_weak_assign(_Tp1* __p, const __shared_count<_Lp>& __n) const
973
        { _M_weak_this._M_assign(__p, __n); }
974
 
975
      template<typename _Tp1>
976
        friend void
977
        __enable_shared_from_this_helper(const __shared_count<_Lp>& __pn,
978
                                         const __enable_shared_from_this* __pe,
979
                                         const _Tp1* __px)
980
        {
981
          if (__pe != 0)
982
            __pe->_M_weak_assign(const_cast<_Tp1*>(__px), __pn);
983
        }
984
 
985
      mutable __weak_ptr<_Tp, _Lp>  _M_weak_this;
986
    };
987
 
988
 
989
  // The actual shared_ptr, with forwarding constructors and
990
  // assignment operators.
991
  template<typename _Tp>
992
    class shared_ptr
993
    : public __shared_ptr<_Tp>
994
    {
995
    public:
996
      shared_ptr()
997
      : __shared_ptr<_Tp>() { }
998
 
999
      template<typename _Tp1>
1000
        explicit
1001
        shared_ptr(_Tp1* __p)
1002
        : __shared_ptr<_Tp>(__p) { }
1003
 
1004
      template<typename _Tp1, typename _Deleter>
1005
        shared_ptr(_Tp1* __p, _Deleter __d)
1006
        : __shared_ptr<_Tp>(__p, __d) { }
1007
 
1008
      template<typename _Tp1>
1009
        shared_ptr(const shared_ptr<_Tp1>& __r)
1010
        : __shared_ptr<_Tp>(__r) { }
1011
 
1012
      template<typename _Tp1>
1013
        explicit
1014
        shared_ptr(const weak_ptr<_Tp1>& __r)
1015
        : __shared_ptr<_Tp>(__r) { }
1016
 
1017
#if !defined(__GXX_EXPERIMENTAL_CXX0X__) || _GLIBCXX_USE_DEPRECATED
1018
      template<typename _Tp1>
1019
        explicit
1020
        shared_ptr(std::auto_ptr<_Tp1>& __r)
1021
        : __shared_ptr<_Tp>(__r) { }
1022
#endif
1023
 
1024
      template<typename _Tp1>
1025
        shared_ptr(const shared_ptr<_Tp1>& __r, __static_cast_tag)
1026
        : __shared_ptr<_Tp>(__r, __static_cast_tag()) { }
1027
 
1028
      template<typename _Tp1>
1029
        shared_ptr(const shared_ptr<_Tp1>& __r, __const_cast_tag)
1030
        : __shared_ptr<_Tp>(__r, __const_cast_tag()) { }
1031
 
1032
      template<typename _Tp1>
1033
        shared_ptr(const shared_ptr<_Tp1>& __r, __dynamic_cast_tag)
1034
        : __shared_ptr<_Tp>(__r, __dynamic_cast_tag()) { }
1035
 
1036
      template<typename _Tp1>
1037
        shared_ptr&
1038
        operator=(const shared_ptr<_Tp1>& __r) // never throws
1039
        {
1040
          this->__shared_ptr<_Tp>::operator=(__r);
1041
          return *this;
1042
        }
1043
 
1044
#if !defined(__GXX_EXPERIMENTAL_CXX0X__) || _GLIBCXX_USE_DEPRECATED
1045
      template<typename _Tp1>
1046
        shared_ptr&
1047
        operator=(std::auto_ptr<_Tp1>& __r)
1048
        {
1049
          this->__shared_ptr<_Tp>::operator=(__r);
1050
          return *this;
1051
        }
1052
#endif
1053
    };
1054
 
1055
  // 2.2.3.8 shared_ptr specialized algorithms.
1056
  template<typename _Tp>
1057
    inline void
1058
    swap(__shared_ptr<_Tp>& __a, __shared_ptr<_Tp>& __b)
1059
    { __a.swap(__b); }
1060
 
1061
  template<typename _Tp, typename _Tp1>
1062
    inline shared_ptr<_Tp>
1063
    static_pointer_cast(const shared_ptr<_Tp1>& __r)
1064
    { return shared_ptr<_Tp>(__r, __static_cast_tag()); }
1065
 
1066
  template<typename _Tp, typename _Tp1>
1067
    inline shared_ptr<_Tp>
1068
    const_pointer_cast(const shared_ptr<_Tp1>& __r)
1069
    { return shared_ptr<_Tp>(__r, __const_cast_tag()); }
1070
 
1071
  template<typename _Tp, typename _Tp1>
1072
    inline shared_ptr<_Tp>
1073
    dynamic_pointer_cast(const shared_ptr<_Tp1>& __r)
1074
    { return shared_ptr<_Tp>(__r, __dynamic_cast_tag()); }
1075
 
1076
 
1077
  // The actual weak_ptr, with forwarding constructors and
1078
  // assignment operators.
1079
  template<typename _Tp>
1080
    class weak_ptr
1081
    : public __weak_ptr<_Tp>
1082
    {
1083
    public:
1084
      weak_ptr()
1085
      : __weak_ptr<_Tp>() { }
1086
 
1087
      template<typename _Tp1>
1088
        weak_ptr(const weak_ptr<_Tp1>& __r)
1089
        : __weak_ptr<_Tp>(__r) { }
1090
 
1091
      template<typename _Tp1>
1092
        weak_ptr(const shared_ptr<_Tp1>& __r)
1093
        : __weak_ptr<_Tp>(__r) { }
1094
 
1095
      template<typename _Tp1>
1096
        weak_ptr&
1097
        operator=(const weak_ptr<_Tp1>& __r) // never throws
1098
        {
1099
          this->__weak_ptr<_Tp>::operator=(__r);
1100
          return *this;
1101
        }
1102
 
1103
      template<typename _Tp1>
1104
        weak_ptr&
1105
        operator=(const shared_ptr<_Tp1>& __r) // never throws
1106
        {
1107
          this->__weak_ptr<_Tp>::operator=(__r);
1108
          return *this;
1109
        }
1110
 
1111
      shared_ptr<_Tp>
1112
      lock() const // never throws
1113
      {
1114
#ifdef __GTHREADS
1115
        if (this->expired())
1116
          return shared_ptr<_Tp>();
1117
 
1118
        __try
1119
          {
1120
            return shared_ptr<_Tp>(*this);
1121
          }
1122
        __catch(const bad_weak_ptr&)
1123
          {
1124
            return shared_ptr<_Tp>();
1125
          }
1126
#else
1127
        return this->expired() ? shared_ptr<_Tp>()
1128
                               : shared_ptr<_Tp>(*this);
1129
#endif
1130
      }
1131
    };
1132
 
1133
  template<typename _Tp>
1134
    class enable_shared_from_this
1135
    {
1136
    protected:
1137
      enable_shared_from_this() { }
1138
 
1139
      enable_shared_from_this(const enable_shared_from_this&) { }
1140
 
1141
      enable_shared_from_this&
1142
      operator=(const enable_shared_from_this&)
1143
      { return *this; }
1144
 
1145
      ~enable_shared_from_this() { }
1146
 
1147
    public:
1148
      shared_ptr<_Tp>
1149
      shared_from_this()
1150
      { return shared_ptr<_Tp>(this->_M_weak_this); }
1151
 
1152
      shared_ptr<const _Tp>
1153
      shared_from_this() const
1154
      { return shared_ptr<const _Tp>(this->_M_weak_this); }
1155
 
1156
    private:
1157
      template<typename _Tp1>
1158
        void
1159
        _M_weak_assign(_Tp1* __p, const __shared_count<>& __n) const
1160
        { _M_weak_this._M_assign(__p, __n); }
1161
 
1162
      template<typename _Tp1>
1163
        friend void
1164
        __enable_shared_from_this_helper(const __shared_count<>& __pn,
1165
                                         const enable_shared_from_this* __pe,
1166
                                         const _Tp1* __px)
1167
        {
1168
          if (__pe != 0)
1169
            __pe->_M_weak_assign(const_cast<_Tp1*>(__px), __pn);
1170
        }
1171
 
1172
      mutable weak_ptr<_Tp>  _M_weak_this;
1173
    };
1174
 
1175
_GLIBCXX_END_NAMESPACE_VERSION
1176
}
1177
}
1178
 
1179
#endif // _TR1_SHARED_PTR_H

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.