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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-stable/] [gcc-4.5.1/] [libstdc++-v3/] [include/] [tr1_impl/] [boost_sp_counted_base.h] - Blame information for rev 826

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 424 jeremybenn
// <tr1_impl/boost_sp_counted_base.h> -*- C++ -*-
2
 
3
// Copyright (C) 2007, 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_impl/boost_sp_counted_base.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
 
50
namespace std
51
{
52
_GLIBCXX_BEGIN_NAMESPACE_TR1
53
 
54
 /**
55
   *  @brief  Exception possibly thrown by @c shared_ptr.
56
   *  @ingroup exceptions
57
   */
58
  class bad_weak_ptr : public std::exception
59
  {
60
  public:
61
    virtual char const*
62
    what() const throw()
63
#ifdef _GLIBCXX_INCLUDE_AS_CXX0X
64
    { return "std::bad_weak_ptr"; }
65
#else
66
    { return "tr1::bad_weak_ptr"; }
67
#endif
68
  };
69
 
70
  // Substitute for bad_weak_ptr object in the case of -fno-exceptions.
71
  inline void
72
  __throw_bad_weak_ptr()
73
  {
74
#if __EXCEPTIONS
75
    throw bad_weak_ptr();
76
#else
77
    __builtin_abort();
78
#endif
79
  }
80
 
81
  using __gnu_cxx::_Lock_policy;
82
  using __gnu_cxx::__default_lock_policy;
83
  using __gnu_cxx::_S_single;
84
  using __gnu_cxx::_S_mutex;
85
  using __gnu_cxx::_S_atomic;
86
 
87
  // Empty helper class except when the template argument is _S_mutex.
88
  template<_Lock_policy _Lp>
89
    class _Mutex_base
90
    {
91
    protected:
92
      // The atomic policy uses fully-fenced builtins, single doesn't care.
93
      enum { _S_need_barriers = 0 };
94
    };
95
 
96
  template<>
97
    class _Mutex_base<_S_mutex>
98
    : public __gnu_cxx::__mutex
99
    {
100
    protected:
101
      // This policy is used when atomic builtins are not available.
102
      // The replacement atomic operations might not have the necessary
103
      // memory barriers.
104
      enum { _S_need_barriers = 1 };
105
    };
106
 
107
  template<_Lock_policy _Lp = __default_lock_policy>
108
    class _Sp_counted_base
109
    : public _Mutex_base<_Lp>
110
    {
111
    public:
112
      _Sp_counted_base()
113
      : _M_use_count(1), _M_weak_count(1) { }
114
 
115
      virtual
116
      ~_Sp_counted_base() // nothrow 
117
      { }
118
 
119
      // Called when _M_use_count drops to zero, to release the resources
120
      // managed by *this.
121
      virtual void
122
      _M_dispose() = 0; // nothrow
123
 
124
      // Called when _M_weak_count drops to zero.
125
      virtual void
126
      _M_destroy() // nothrow
127
      { delete this; }
128
 
129
      virtual void*
130
      _M_get_deleter(const std::type_info&) = 0;
131
 
132
      void
133
      _M_add_ref_copy()
134
      { __gnu_cxx::__atomic_add_dispatch(&_M_use_count, 1); }
135
 
136
      void
137
      _M_add_ref_lock();
138
 
139
      void
140
      _M_release() // nothrow
141
      {
142
        if (__gnu_cxx::__exchange_and_add_dispatch(&_M_use_count, -1) == 1)
143
          {
144
            _M_dispose();
145
            // There must be a memory barrier between dispose() and destroy()
146
            // to ensure that the effects of dispose() are observed in the
147
            // thread that runs destroy().
148
            // See http://gcc.gnu.org/ml/libstdc++/2005-11/msg00136.html
149
            if (_Mutex_base<_Lp>::_S_need_barriers)
150
              {
151
                _GLIBCXX_READ_MEM_BARRIER;
152
                _GLIBCXX_WRITE_MEM_BARRIER;
153
              }
154
 
155
            if (__gnu_cxx::__exchange_and_add_dispatch(&_M_weak_count,
156
                                                       -1) == 1)
157
              _M_destroy();
158
          }
159
      }
160
 
161
      void
162
      _M_weak_add_ref() // nothrow
163
      { __gnu_cxx::__atomic_add_dispatch(&_M_weak_count, 1); }
164
 
165
      void
166
      _M_weak_release() // nothrow
167
      {
168
        if (__gnu_cxx::__exchange_and_add_dispatch(&_M_weak_count, -1) == 1)
169
          {
170
            if (_Mutex_base<_Lp>::_S_need_barriers)
171
              {
172
                // See _M_release(),
173
                // destroy() must observe results of dispose()
174
                _GLIBCXX_READ_MEM_BARRIER;
175
                _GLIBCXX_WRITE_MEM_BARRIER;
176
              }
177
            _M_destroy();
178
          }
179
      }
180
 
181
      long
182
      _M_get_use_count() const // nothrow
183
      {
184
        // No memory barrier is used here so there is no synchronization
185
        // with other threads.
186
        return const_cast<const volatile _Atomic_word&>(_M_use_count);
187
      }
188
 
189
    private:
190
      _Sp_counted_base(_Sp_counted_base const&);
191
      _Sp_counted_base& operator=(_Sp_counted_base const&);
192
 
193
      _Atomic_word  _M_use_count;     // #shared
194
      _Atomic_word  _M_weak_count;    // #weak + (#shared != 0)
195
    };
196
 
197
  template<>
198
    inline void
199
    _Sp_counted_base<_S_single>::
200
    _M_add_ref_lock()
201
    {
202
      if (__gnu_cxx::__exchange_and_add_dispatch(&_M_use_count, 1) == 0)
203
        {
204
          _M_use_count = 0;
205
          __throw_bad_weak_ptr();
206
        }
207
    }
208
 
209
  template<>
210
    inline void
211
    _Sp_counted_base<_S_mutex>::
212
    _M_add_ref_lock()
213
    {
214
      __gnu_cxx::__scoped_lock sentry(*this);
215
      if (__gnu_cxx::__exchange_and_add_dispatch(&_M_use_count, 1) == 0)
216
        {
217
          _M_use_count = 0;
218
          __throw_bad_weak_ptr();
219
        }
220
    }
221
 
222
  template<>
223
    inline void
224
    _Sp_counted_base<_S_atomic>::
225
    _M_add_ref_lock()
226
    {
227
      // Perform lock-free add-if-not-zero operation.
228
      _Atomic_word __count;
229
      do
230
        {
231
          __count = _M_use_count;
232
          if (__count == 0)
233
            __throw_bad_weak_ptr();
234
 
235
          // Replace the current counter value with the old value + 1, as
236
          // long as it's not changed meanwhile. 
237
        }
238
      while (!__sync_bool_compare_and_swap(&_M_use_count, __count,
239
                                           __count + 1));
240
    }
241
 
242
_GLIBCXX_END_NAMESPACE_TR1
243
}

powered by: WebSVN 2.1.0

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