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 if (__gnu_cxx::__exchange_and_add_dispatch(&_M_use_count, -1) == 1)
00143 {
00144 _M_dispose();
00145
00146
00147
00148
00149 if (_Mutex_base<_Lp>::_S_need_barriers)
00150 {
00151 _GLIBCXX_READ_MEM_BARRIER;
00152 _GLIBCXX_WRITE_MEM_BARRIER;
00153 }
00154
00155 if (__gnu_cxx::__exchange_and_add_dispatch(&_M_weak_count,
00156 -1) == 1)
00157 _M_destroy();
00158 }
00159 }
00160
00161 void
00162 _M_weak_add_ref()
00163 { __gnu_cxx::__atomic_add_dispatch(&_M_weak_count, 1); }
00164
00165 void
00166 _M_weak_release()
00167 {
00168 if (__gnu_cxx::__exchange_and_add_dispatch(&_M_weak_count, -1) == 1)
00169 {
00170 if (_Mutex_base<_Lp>::_S_need_barriers)
00171 {
00172
00173
00174 _GLIBCXX_READ_MEM_BARRIER;
00175 _GLIBCXX_WRITE_MEM_BARRIER;
00176 }
00177 _M_destroy();
00178 }
00179 }
00180
00181 long
00182 _M_get_use_count() const
00183 {
00184
00185
00186 return const_cast<const volatile _Atomic_word&>(_M_use_count);
00187 }
00188
00189 private:
00190 _Sp_counted_base(_Sp_counted_base const&);
00191 _Sp_counted_base& operator=(_Sp_counted_base const&);
00192
00193 _Atomic_word _M_use_count;
00194 _Atomic_word _M_weak_count;
00195 };
00196
00197 template<>
00198 inline void
00199 _Sp_counted_base<_S_single>::
00200 _M_add_ref_lock()
00201 {
00202 if (__gnu_cxx::__exchange_and_add_dispatch(&_M_use_count, 1) == 0)
00203 {
00204 _M_use_count = 0;
00205 __throw_bad_weak_ptr();
00206 }
00207 }
00208
00209 template<>
00210 inline void
00211 _Sp_counted_base<_S_mutex>::
00212 _M_add_ref_lock()
00213 {
00214 __gnu_cxx::__scoped_lock sentry(*this);
00215 if (__gnu_cxx::__exchange_and_add_dispatch(&_M_use_count, 1) == 0)
00216 {
00217 _M_use_count = 0;
00218 __throw_bad_weak_ptr();
00219 }
00220 }
00221
00222 template<>
00223 inline void
00224 _Sp_counted_base<_S_atomic>::
00225 _M_add_ref_lock()
00226 {
00227
00228 _Atomic_word __count;
00229 do
00230 {
00231 __count = _M_use_count;
00232 if (__count == 0)
00233 __throw_bad_weak_ptr();
00234
00235
00236
00237 }
00238 while (!__sync_bool_compare_and_swap(&_M_use_count, __count,
00239 __count + 1));
00240 }
00241
00242 _GLIBCXX_END_NAMESPACE_TR1
00243 }