boost_sp_counted_base.h
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
00051
00052
00053
00054
00055 namespace std
00056 {
00057 _GLIBCXX_BEGIN_NAMESPACE_TR1
00058
00059 class bad_weak_ptr : public std::exception
00060 {
00061 public:
00062 virtual char const*
00063 what() const throw()
00064 #ifdef _GLIBCXX_INCLUDE_AS_CXX0X
00065 { return "std::bad_weak_ptr"; }
00066 #else
00067 { return "tr1::bad_weak_ptr"; }
00068 #endif
00069 };
00070
00071
00072 inline void
00073 __throw_bad_weak_ptr()
00074 {
00075 #if __EXCEPTIONS
00076 throw bad_weak_ptr();
00077 #else
00078 __builtin_abort();
00079 #endif
00080 }
00081
00082 using __gnu_cxx::_Lock_policy;
00083 using __gnu_cxx::__default_lock_policy;
00084 using __gnu_cxx::_S_single;
00085 using __gnu_cxx::_S_mutex;
00086 using __gnu_cxx::_S_atomic;
00087
00088
00089 template<_Lock_policy _Lp>
00090 class _Mutex_base
00091 {
00092 protected:
00093
00094 enum { _S_need_barriers = 0 };
00095 };
00096
00097 template<>
00098 class _Mutex_base<_S_mutex>
00099 : public __gnu_cxx::__mutex
00100 {
00101 protected:
00102
00103
00104
00105 enum { _S_need_barriers = 1 };
00106 };
00107
00108 template<_Lock_policy _Lp = __default_lock_policy>
00109 class _Sp_counted_base
00110 : public _Mutex_base<_Lp>
00111 {
00112 public:
00113 _Sp_counted_base()
00114 : _M_use_count(1), _M_weak_count(1) { }
00115
00116 virtual
00117 ~_Sp_counted_base()
00118 { }
00119
00120
00121
00122 virtual void
00123 _M_dispose() = 0;
00124
00125
00126 virtual void
00127 _M_destroy()
00128 { delete this; }
00129
00130 virtual void*
00131 _M_get_deleter(const std::type_info&) = 0;
00132
00133 void
00134 _M_add_ref_copy()
00135 { __gnu_cxx::__atomic_add_dispatch(&_M_use_count, 1); }
00136
00137 void
00138 _M_add_ref_lock();
00139
00140 void
00141 _M_release()
00142 {
00143 if (__gnu_cxx::__exchange_and_add_dispatch(&_M_use_count, -1) == 1)
00144 {
00145 _M_dispose();
00146
00147
00148
00149
00150 if (_Mutex_base<_Lp>::_S_need_barriers)
00151 {
00152 _GLIBCXX_READ_MEM_BARRIER;
00153 _GLIBCXX_WRITE_MEM_BARRIER;
00154 }
00155
00156 if (__gnu_cxx::__exchange_and_add_dispatch(&_M_weak_count,
00157 -1) == 1)
00158 _M_destroy();
00159 }
00160 }
00161
00162 void
00163 _M_weak_add_ref()
00164 { __gnu_cxx::__atomic_add_dispatch(&_M_weak_count, 1); }
00165
00166 void
00167 _M_weak_release()
00168 {
00169 if (__gnu_cxx::__exchange_and_add_dispatch(&_M_weak_count, -1) == 1)
00170 {
00171 if (_Mutex_base<_Lp>::_S_need_barriers)
00172 {
00173
00174
00175 _GLIBCXX_READ_MEM_BARRIER;
00176 _GLIBCXX_WRITE_MEM_BARRIER;
00177 }
00178 _M_destroy();
00179 }
00180 }
00181
00182 long
00183 _M_get_use_count() const
00184 {
00185
00186
00187 return const_cast<const volatile _Atomic_word&>(_M_use_count);
00188 }
00189
00190 private:
00191 _Sp_counted_base(_Sp_counted_base const&);
00192 _Sp_counted_base& operator=(_Sp_counted_base const&);
00193
00194 _Atomic_word _M_use_count;
00195 _Atomic_word _M_weak_count;
00196 };
00197
00198 template<>
00199 inline void
00200 _Sp_counted_base<_S_single>::
00201 _M_add_ref_lock()
00202 {
00203 if (__gnu_cxx::__exchange_and_add_dispatch(&_M_use_count, 1) == 0)
00204 {
00205 _M_use_count = 0;
00206 __throw_bad_weak_ptr();
00207 }
00208 }
00209
00210 template<>
00211 inline void
00212 _Sp_counted_base<_S_mutex>::
00213 _M_add_ref_lock()
00214 {
00215 __gnu_cxx::__scoped_lock sentry(*this);
00216 if (__gnu_cxx::__exchange_and_add_dispatch(&_M_use_count, 1) == 0)
00217 {
00218 _M_use_count = 0;
00219 __throw_bad_weak_ptr();
00220 }
00221 }
00222
00223 template<>
00224 inline void
00225 _Sp_counted_base<_S_atomic>::
00226 _M_add_ref_lock()
00227 {
00228
00229 _Atomic_word __count;
00230 do
00231 {
00232 __count = _M_use_count;
00233 if (__count == 0)
00234 __throw_bad_weak_ptr();
00235
00236
00237
00238 }
00239 while (!__sync_bool_compare_and_swap(&_M_use_count, __count,
00240 __count + 1));
00241 }
00242
00243 _GLIBCXX_END_NAMESPACE_TR1
00244 }