CppCMS
booster/thread.h
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