Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050 namespace std
00051 {
00052 _GLIBCXX_BEGIN_NAMESPACE_TR1
00053
00054
00055
00056
00057
00058 class bad_weak_ptr : public std::exception
00059 {
00060 public:
00061 virtual char const*
00062 what() const throw()
00063 #ifdef _GLIBCXX_INCLUDE_AS_CXX0X
00064 { return "std::bad_weak_ptr"; }
00065 #else
00066 { return "tr1::bad_weak_ptr"; }
00067 #endif
00068 };
00069
00070
00071 inline void
00072 __throw_bad_weak_ptr()
00073 {
00074 #if __EXCEPTIONS
00075 throw bad_weak_ptr();
00076 #else
00077 __builtin_abort();
00078 #endif
00079 }
00080
00081 using __gnu_cxx::_Lock_policy;
00082 using __gnu_cxx::__default_lock_policy;
00083 using __gnu_cxx::_S_single;
00084 using __gnu_cxx::_S_mutex;
00085 using __gnu_cxx::_S_atomic;
00086
00087
00088 template<_Lock_policy _Lp>
00089 class _Mutex_base
00090 {
00091 protected:
00092
00093 enum { _S_need_barriers = 0 };
00094 };
00095
00096 template<>
00097 class _Mutex_base<_S_mutex>
00098 : public __gnu_cxx::__mutex
00099 {
00100 protected:
00101
00102
00103
00104 enum { _S_need_barriers = 1 };
00105 };
00106
00107 template<_Lock_policy _Lp = __default_lock_policy>
00108 class _Sp_counted_base
00109 : public _Mutex_base<_Lp>
00110 {
00111 public:
00112 _Sp_counted_base()
00113 : _M_use_count(1), _M_weak_count(1) { }
00114
00115 virtual
00116 ~_Sp_counted_base()
00117 { }
00118
00119
00120
00121 virtual void
00122 _M_dispose() = 0;
00123
00124
00125 virtual void
00126 _M_destroy()
00127 { delete this; }
00128
00129 virtual void*
00130 _M_get_deleter(const std::type_info&) = 0;
00131
00132 void
00133 _M_add_ref_copy()
00134 { __gnu_cxx::__atomic_add_dispatch(&_M_use_count, 1); }
00135
00136 void
00137 _M_add_ref_lock();
00138
00139 void
00140 _M_release()
00141 {
00142
00143 _GLIBCXX_SYNCHRONIZATION_HAPPENS_BEFORE(&_M_use_count);
00144 if (__gnu_cxx::__exchange_and_add_dispatch(&_M_use_count, -1) == 1)
00145 {
00146 _GLIBCXX_SYNCHRONIZATION_HAPPENS_AFTER(&_M_use_count);
00147 _M_dispose();
00148
00149
00150
00151
00152 if (_Mutex_base<_Lp>::_S_need_barriers)
00153 {
00154 _GLIBCXX_READ_MEM_BARRIER;
00155 _GLIBCXX_WRITE_MEM_BARRIER;
00156 }
00157
00158
00159 _GLIBCXX_SYNCHRONIZATION_HAPPENS_BEFORE(&_M_weak_count);
00160 if (__gnu_cxx::__exchange_and_add_dispatch(&_M_weak_count,
00161 -1) == 1)
00162 {
00163 _GLIBCXX_SYNCHRONIZATION_HAPPENS_AFTER(&_M_weak_count);
00164 _M_destroy();
00165 }
00166 }
00167 }
00168
00169 void
00170 _M_weak_add_ref()
00171 { __gnu_cxx::__atomic_add_dispatch(&_M_weak_count, 1); }
00172
00173 void
00174 _M_weak_release()
00175 {
00176
00177 _GLIBCXX_SYNCHRONIZATION_HAPPENS_BEFORE(&_M_weak_count);
00178 if (__gnu_cxx::__exchange_and_add_dispatch(&_M_weak_count, -1) == 1)
00179 {
00180 _GLIBCXX_SYNCHRONIZATION_HAPPENS_AFTER(&_M_weak_count);
00181 if (_Mutex_base<_Lp>::_S_need_barriers)
00182 {
00183
00184
00185 _GLIBCXX_READ_MEM_BARRIER;
00186 _GLIBCXX_WRITE_MEM_BARRIER;
00187 }
00188 _M_destroy();
00189 }
00190 }
00191
00192 long
00193 _M_get_use_count() const
00194 {
00195
00196
00197 return const_cast<const volatile _Atomic_word&>(_M_use_count);
00198 }
00199
00200 private:
00201 _Sp_counted_base(_Sp_counted_base const&);
00202 _Sp_counted_base& operator=(_Sp_counted_base const&);
00203
00204 _Atomic_word _M_use_count;
00205 _Atomic_word _M_weak_count;
00206 };
00207
00208 template<>
00209 inline void
00210 _Sp_counted_base<_S_single>::
00211 _M_add_ref_lock()
00212 {
00213 if (__gnu_cxx::__exchange_and_add_dispatch(&_M_use_count, 1) == 0)
00214 {
00215 _M_use_count = 0;
00216 __throw_bad_weak_ptr();
00217 }
00218 }
00219
00220 template<>
00221 inline void
00222 _Sp_counted_base<_S_mutex>::
00223 _M_add_ref_lock()
00224 {
00225 __gnu_cxx::__scoped_lock sentry(*this);
00226 if (__gnu_cxx::__exchange_and_add_dispatch(&_M_use_count, 1) == 0)
00227 {
00228 _M_use_count = 0;
00229 __throw_bad_weak_ptr();
00230 }
00231 }
00232
00233 template<>
00234 inline void
00235 _Sp_counted_base<_S_atomic>::
00236 _M_add_ref_lock()
00237 {
00238
00239 _Atomic_word __count;
00240 do
00241 {
00242 __count = _M_use_count;
00243 if (__count == 0)
00244 __throw_bad_weak_ptr();
00245
00246
00247
00248 }
00249 while (!__sync_bool_compare_and_swap(&_M_use_count, __count,
00250 __count + 1));
00251 }
00252
00253 _GLIBCXX_END_NAMESPACE_TR1
00254 }