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