libmoost
|
00001 /* vim:set ts=3 sw=3 sts=3 et: */ 00098 #ifndef MOOST_GUARDED_PTR_HPP__ 00099 #define MOOST_GUARDED_PTR_HPP__ 00100 00101 #include <cassert> 00102 00103 #include <boost/noncopyable.hpp> 00104 #include <boost/scoped_ptr.hpp> 00105 #include <boost/thread/shared_mutex.hpp> 00106 #include <boost/thread/locks.hpp> 00107 00108 namespace moost { 00109 00119 template<typename T> 00120 class guarded_ptr : boost::noncopyable 00121 { 00122 public: 00123 typedef T element_type; 00124 typedef T value_type; 00125 typedef T * pointer; 00126 typedef T const * const_pointer; 00127 typedef T & reference; 00128 typedef T const & const_reference; 00129 00138 class shared_access : boost::noncopyable 00139 { 00140 public: 00141 shared_access(guarded_ptr const & guard) 00142 : m_gptr(guard) 00143 { 00144 m_gptr.m_mutex.lock_shared(); 00145 } 00146 00147 ~shared_access() 00148 { 00149 m_gptr.m_mutex.unlock_shared(); 00150 } 00151 00152 const_reference operator*() const 00153 { 00154 return *(m_gptr.m_ptr); 00155 } 00156 const_pointer operator->() const 00157 { 00158 return m_gptr.m_ptr.get(); 00159 } 00160 00161 private: 00162 guarded_ptr const & m_gptr; 00163 }; 00164 00173 class exclusive_access : boost::noncopyable 00174 { 00175 public: 00176 exclusive_access(guarded_ptr &guard) 00177 : m_gptr(guard) 00178 { 00179 m_gptr.m_mutex.lock(); 00180 } 00181 00182 ~exclusive_access() 00183 { 00184 m_gptr.m_mutex.unlock(); 00185 } 00186 00187 reference operator*() 00188 { 00189 return *(m_gptr.m_ptr); 00190 } 00191 const_reference operator*() const 00192 { 00193 return *(m_gptr.m_ptr); 00194 } 00195 pointer operator->() 00196 { 00197 return m_gptr.m_ptr.get(); 00198 } 00199 const_pointer operator->() const 00200 { 00201 return m_gptr.m_ptr.get(); 00202 } 00203 00204 private: 00205 guarded_ptr & m_gptr; 00206 }; 00207 00219 class upgradable_access : boost::noncopyable 00220 { 00221 public: 00222 upgradable_access(guarded_ptr &guard) 00223 : m_gptr(guard) 00224 , m_upgraded(false) 00225 { 00226 m_gptr.m_mutex.lock_upgrade(); 00227 } 00228 ~upgradable_access() 00229 { 00230 if (m_upgraded) 00231 { 00232 m_gptr.m_mutex.unlock(); 00233 } 00234 else 00235 { 00236 m_gptr.m_mutex.unlock_upgrade(); 00237 } 00238 } 00239 00240 const_reference operator*() const 00241 { 00242 return *(m_gptr.m_ptr); 00243 } 00244 const_pointer operator->() const 00245 { 00246 return m_gptr.m_ptr.get(); 00247 } 00248 00259 class upgrade 00260 { 00261 public: 00262 upgrade(upgradable_access & parent) 00263 : m_parent(parent) 00264 { 00265 parent.m_gptr.m_mutex.unlock_upgrade_and_lock(); 00266 parent.m_upgraded = true; 00267 } 00268 00269 reference operator*() 00270 { 00271 return *(m_parent.m_gptr.m_ptr); 00272 } 00273 const_reference operator*() const 00274 { 00275 return *(m_parent.m_gptr.m_ptr); 00276 } 00277 pointer operator->() 00278 { 00279 return m_parent.m_gptr.m_ptr.get(); 00280 } 00281 const_pointer operator->() const 00282 { 00283 return m_parent.m_gptr.m_ptr.get(); 00284 } 00285 00286 private: 00287 upgradable_access & m_parent; 00288 }; 00289 00290 private: 00291 guarded_ptr & m_gptr; 00292 bool m_upgraded; 00293 }; 00294 00295 guarded_ptr(pointer ptr) 00296 : m_ptr(assert_not_null(ptr)) // do the assert early during construction 00297 { 00298 } 00299 00300 private: 00301 pointer assert_not_null(pointer ptr) 00302 { 00303 assert(ptr); 00304 return ptr; 00305 } 00306 00307 boost::scoped_ptr<element_type> const m_ptr; 00308 boost::shared_mutex mutable m_mutex; 00309 }; 00310 00311 } // namespace moost 00312 00313 #endif // ifndef MOOST_GUARDED_PTR_HPP__