CppCMS
|
00001 // 00002 // Copyright (C) 2009-2012 Artyom Beilis (Tonkikh) 00003 // 00004 // Distributed under the Boost Software License, Version 1.0. (See 00005 // accompanying file LICENSE_1_0.txt or copy at 00006 // http://www.boost.org/LICENSE_1_0.txt) 00007 // 00008 #ifndef BOOSTER_UTIL_THREAD_H 00009 #define BOOSTER_UTIL_THREAD_H 00010 00011 #include <booster/hold_ptr.h> 00012 #include <booster/noncopyable.h> 00013 #include <booster/refcounted.h> 00014 #include <booster/intrusive_ptr.h> 00015 #include <booster/function.h> 00016 #include <booster/config.h> 00017 00018 namespace booster { 00019 00020 extern "C" void *booster_thread_func(void *); 00021 00025 class BOOSTER_API thread : public noncopyable { 00026 public: 00030 thread(function<void()> const &cb); 00031 ~thread(); 00032 00036 void join(); 00037 00041 void detach(); 00042 00046 static unsigned hardware_concurrency(); 00047 private: 00048 friend void *booster_thread_func(void *); 00049 struct data; 00050 hold_ptr<data> d; 00051 }; 00052 00053 00054 class condition_variable; 00055 00059 class BOOSTER_API mutex : public noncopyable { 00060 public: 00061 mutex(); 00062 ~mutex(); 00069 void lock(); 00075 void unlock(); 00076 friend class condition_variable; 00077 private: 00078 struct data; 00079 hold_ptr<data> d; 00080 }; 00081 00106 class BOOSTER_API recursive_mutex : public noncopyable { 00107 public: 00108 recursive_mutex(); 00109 ~recursive_mutex(); 00113 void lock(); 00117 void unlock(); 00118 private: 00119 struct data; 00120 hold_ptr<data> d; 00121 }; 00122 00129 class BOOSTER_API recursive_shared_mutex : public noncopyable { 00130 public: 00131 recursive_shared_mutex(); 00132 ~recursive_shared_mutex(); 00138 void lock() { unique_lock(); } 00144 void unique_lock(); 00151 void shared_lock(); 00155 void unlock(); 00156 private: 00157 struct data; 00158 hold_ptr<data> d; 00159 }; 00166 class BOOSTER_API shared_mutex : public noncopyable { 00167 public: 00168 shared_mutex(); 00169 ~shared_mutex(); 00173 void lock() { unique_lock(); } 00177 void unique_lock(); 00183 void shared_lock(); 00187 void unlock(); 00188 private: 00189 struct data; 00190 hold_ptr<data> d; 00191 }; 00192 00193 template<typename Mutex> 00194 class unique_lock; 00195 00201 class BOOSTER_API condition_variable { 00202 public: 00203 condition_variable(); 00204 ~condition_variable(); 00205 00214 void wait(unique_lock<mutex> &m); 00215 00220 void notify_one(); 00225 void notify_all(); 00226 private: 00227 struct data; 00228 hold_ptr<data> d; 00229 }; 00230 00232 namespace details { 00233 struct tls_object; 00234 00235 class key : public refcounted { 00236 public: 00237 key(void (*d)(void *)) : 00238 dtor_(d) 00239 { 00240 } 00241 virtual ~key() 00242 { 00243 } 00244 void *get(); 00245 void set(void *); 00246 00247 void destroy(void *p) 00248 { 00249 dtor_(p); 00250 } 00251 virtual tls_object *get_object() = 0; 00252 private: 00253 void (*dtor_)(void *); 00254 }; 00255 00256 BOOSTER_API intrusive_ptr<key> make_key(void (*dtor)(void *)); 00257 00258 struct tls_object { 00259 tls_object(intrusive_ptr<key> p) : 00260 the_key(p), 00261 obj(0) 00262 { 00263 } 00264 ~tls_object() 00265 { 00266 the_key->destroy(obj); 00267 obj = 0; 00268 } 00269 intrusive_ptr<key> the_key; 00270 void *obj; 00271 }; 00272 00273 inline void key::set(void *p) 00274 { 00275 get_object()->obj = p; 00276 } 00277 inline void *key::get() 00278 { 00279 return get_object()->obj; 00280 } 00281 00282 } // details 00283 00285 00309 template<typename T> 00310 class thread_specific_ptr { 00311 public: 00315 thread_specific_ptr() : key_(details::make_key(destructor)) 00316 { 00317 } 00318 00322 ~thread_specific_ptr() 00323 { 00324 } 00328 T *get() const 00329 { 00330 return static_cast<T*>(key_->get()); 00331 } 00335 T* operator->() const 00336 { 00337 return get(); 00338 } 00342 T& operator*() const 00343 { 00344 return *get(); 00345 } 00351 void reset(T *new_val = 0) 00352 { 00353 T *p = get(); 00354 if(p) 00355 destructor(p); 00356 key_->set(static_cast<void *>(new_val)); 00357 } 00363 T *release() 00364 { 00365 T *p = get(); 00366 key_->set(0); 00367 return p; 00368 } 00369 private: 00370 static void destructor(void *ptr) 00371 { 00372 delete static_cast<T*>(ptr); 00373 } 00374 intrusive_ptr<details::key> key_; 00375 }; 00376 00377 00383 template<typename Mutex> 00384 class unique_lock : public noncopyable { 00385 public: 00387 unique_lock(Mutex &m) : m_(&m) 00388 { 00389 m_->lock(); 00390 } 00392 ~unique_lock() 00393 { 00394 m_->unlock(); 00395 } 00397 Mutex *mutex() const 00398 { 00399 return m_; 00400 } 00401 private: 00402 Mutex *m_; 00403 }; 00404 00410 template<typename Mutex> 00411 class shared_lock : public noncopyable { 00412 public: 00414 shared_lock(Mutex &m) : m_(&m) 00415 { 00416 m_->shared_lock(); 00417 } 00419 ~shared_lock() 00420 { 00421 m_->unlock(); 00422 } 00424 Mutex *mutex() const 00425 { 00426 return m_; 00427 } 00428 private: 00429 Mutex *m_; 00430 }; 00431 #ifdef BOOSTER_POSIX 00432 00433 00434 00435 00436 00437 class BOOSTER_API fork_shared_mutex : public noncopyable { 00438 public: 00442 fork_shared_mutex(); 00443 ~fork_shared_mutex(); 00444 00448 bool try_lock() { return try_unique_lock(); } 00452 bool try_unique_lock(); 00456 bool try_shared_lock(); 00457 00461 void lock() { return unique_lock(); } 00465 void unique_lock(); 00469 void shared_lock(); 00470 00474 void unlock(); 00475 private: 00476 struct data; 00477 hold_ptr<data> d; 00478 }; 00479 #endif 00480 00481 }//booster 00482 00483 00484 #endif