00001
00002
00003
00004
00005
00006
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 }
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 }
00482
00483
00484 #endif