ucommon
ucommon/thread.h
Go to the documentation of this file.
00001 // Copyright (C) 2006-2014 David Sugar, Tycho Softworks.
00002 //
00003 // This file is part of GNU uCommon C++.
00004 //
00005 // GNU uCommon C++ is free software: you can redistribute it and/or modify
00006 // it under the terms of the GNU Lesser General Public License as published
00007 // by the Free Software Foundation, either version 3 of the License, or
00008 // (at your option) any later version.
00009 //
00010 // GNU uCommon C++ is distributed in the hope that it will be useful,
00011 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00012 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013 // GNU Lesser General Public License for more details.
00014 //
00015 // You should have received a copy of the GNU Lesser General Public License
00016 // along with GNU uCommon C++.  If not, see <http://www.gnu.org/licenses/>.
00017 
00053 #ifndef _UCOMMON_THREAD_H_
00054 #define _UCOMMON_THREAD_H_
00055 
00056 #ifndef _UCOMMON_CPR_H_
00057 #include <ucommon/cpr.h>
00058 #endif
00059 
00060 #ifndef _UCOMMON_ACCESS_H_
00061 #include <ucommon/access.h>
00062 #endif
00063 
00064 #ifndef _UCOMMON_TIMERS_H_
00065 #include <ucommon/timers.h>
00066 #endif
00067 
00068 #ifndef _UCOMMON_MEMORY_H_
00069 #include <ucommon/memory.h>
00070 #endif
00071 
00072 namespace ucommon {
00073 
00074 class SharedPointer;
00075 
00086 class __EXPORT Conditional
00087 {
00088 private:
00089     friend class ConditionalAccess;
00090 
00091 #if defined(_MSCONDITIONAL_)
00092     CRITICAL_SECTION mutex;
00093     CONDITION_VARIABLE cond;
00094 #elif defined(_MSTHREADS_)
00095     enum {SIGNAL = 0, BROADCAST = 1};
00096     HANDLE events[2];
00097     unsigned waiting;
00098     CRITICAL_SECTION mlock;
00099     CRITICAL_SECTION mutex;
00100 #else
00101 #ifndef __PTH__
00102     class __LOCAL attribute
00103     {
00104     public:
00105         pthread_condattr_t attr;
00106         attribute();
00107     };
00108 
00109     __LOCAL static attribute attr;
00110 #endif
00111 
00112     pthread_cond_t cond;
00113     pthread_mutex_t mutex;
00114 #endif
00115 
00116 protected:
00117     friend class TimedEvent;
00118 
00124     bool wait(timeout_t timeout);
00125 
00131     bool wait(struct timespec *timeout);
00132 
00133 #ifdef  _MSTHREADS_
00134     inline void lock(void)
00135         {EnterCriticalSection(&mutex);};
00136 
00137     inline void unlock(void)
00138         {LeaveCriticalSection(&mutex);};
00139 
00140     void wait(void);
00141     void signal(void);
00142     void broadcast(void);
00143 
00144 #else
00145 
00148     inline void lock(void)
00149         {pthread_mutex_lock(&mutex);}
00150 
00154     inline void unlock(void)
00155         {pthread_mutex_unlock(&mutex);}
00156 
00160     inline void wait(void)
00161         {pthread_cond_wait(&cond, &mutex);}
00162 
00166     inline void signal(void)
00167         {pthread_cond_signal(&cond);}
00168 
00172     inline void broadcast(void)
00173         {pthread_cond_broadcast(&cond);}
00174 #endif
00175 
00179     Conditional();
00180 
00184     ~Conditional();
00185 
00186 public:
00187 #if !defined(_MSTHREADS_) && !defined(__PTH__)
00188 
00193     static inline pthread_condattr_t *initializer(void)
00194         {return &attr.attr;}
00195 #endif
00196 
00203     static void set(struct timespec *hires, timeout_t timeout);
00204 };
00205 
00213 class __EXPORT ConditionalAccess : private Conditional
00214 {
00215 protected:
00216 #if defined _MSCONDITIONAL_
00217     CONDITION_VARIABLE bcast;
00218 #elif !defined(_MSTHREADS_)
00219     pthread_cond_t bcast;
00220 #endif
00221 
00222     unsigned pending, waiting, sharing;
00223 
00229     bool waitSignal(timeout_t timeout);
00230 
00236     bool waitBroadcast(timeout_t timeout);
00237 
00238 
00244     bool waitSignal(struct timespec *timeout);
00245 
00251     bool waitBroadcast(struct timespec *timeout);
00252 
00259     inline static void set(struct timespec *hires, timeout_t timeout)
00260         {Conditional::set(hires, timeout);}
00261 
00262 
00263 #ifdef  _MSTHREADS_
00264     inline void lock(void)
00265         {EnterCriticalSection(&mutex);};
00266 
00267     inline void unlock(void)
00268         {LeaveCriticalSection(&mutex);};
00269 
00270     void waitSignal(void);
00271     void waitBroadcast(void);
00272 
00273     inline void signal(void)
00274         {Conditional::signal();};
00275 
00276     inline void broadcast(void)
00277         {Conditional::broadcast();};
00278 
00279 #else
00280 
00283     inline void lock(void)
00284         {pthread_mutex_lock(&mutex);}
00285 
00289     inline void unlock(void)
00290         {pthread_mutex_unlock(&mutex);}
00291 
00295     inline void waitSignal(void)
00296         {pthread_cond_wait(&cond, &mutex);}
00297 
00301     inline void waitBroadcast(void)
00302         {pthread_cond_wait(&bcast, &mutex);}
00303 
00304 
00308     inline void signal(void)
00309         {pthread_cond_signal(&cond);}
00310 
00314     inline void broadcast(void)
00315         {pthread_cond_broadcast(&bcast);}
00316 #endif
00317 public:
00321     ConditionalAccess();
00322 
00326     ~ConditionalAccess();
00327 
00331     void access(void);
00332 
00336     void modify(void);
00337 
00341     void release(void);
00342 
00346     void commit(void);
00347 
00354     void limit_sharing(unsigned max);
00355 };
00356 
00365 class __EXPORT TimedEvent : public Timer
00366 {
00367 private:
00368 #ifdef _MSTHREADS_
00369     HANDLE event;
00370 #else
00371     pthread_cond_t cond;
00372     bool signalled;
00373 #endif
00374     pthread_mutex_t mutex;
00375 
00376 protected:
00381     void lock(void);
00382 
00387     void release(void);
00388 
00396     bool sync(void);
00397 
00398 public:
00402     TimedEvent(void);
00403 
00408     TimedEvent(timeout_t timeout);
00409 
00414     TimedEvent(time_t timeout);
00415 
00419     ~TimedEvent();
00420 
00426     void signal(void);
00427 
00434     bool wait(timeout_t timeout);
00435 
00439     void wait(void);
00440 
00444     void reset(void);
00445 };
00446 
00454 class __EXPORT RecursiveMutex : private Conditional, public ExclusiveAccess
00455 {
00456 protected:
00457     unsigned waiting;
00458     unsigned lockers;
00459     pthread_t locker;
00460 
00461     virtual void _lock(void);
00462     virtual void _unlock(void);
00463 
00464 public:
00468     RecursiveMutex();
00469 
00473     void lock(void);
00474 
00478     bool lock(timeout_t timeout);
00479 
00483     void release(void);
00484 };
00485 
00498 class __EXPORT ThreadLock : private ConditionalAccess, public ExclusiveAccess, public SharedAccess
00499 {
00500 protected:
00501     unsigned writers;
00502     pthread_t writeid;
00503 
00504     virtual void _lock(void);
00505     virtual void _share(void);
00506     virtual void _unlock(void);
00507 
00508 public:
00516     class __EXPORT guard_reader
00517     {
00518     private:
00519         const void *object;
00520 
00521     public:
00526         guard_reader();
00527 
00532         guard_reader(const void *object);
00533 
00537         ~guard_reader();
00538 
00544         void set(const void *object);
00545 
00549         void release(void);
00550 
00556         inline void operator=(const void *pointer)
00557             {set(pointer);}
00558     };
00559 
00567     class __EXPORT guard_writer
00568     {
00569     private:
00570         const void *object;
00571 
00572     public:
00577         guard_writer();
00578 
00583         guard_writer(const void *object);
00584 
00588         ~guard_writer();
00589 
00595         void set(const void *object);
00596 
00600         void release(void);
00601 
00607         inline void operator=(const void *pointer)
00608             {set(pointer);}
00609     };
00610 
00614     ThreadLock();
00615 
00621     bool modify(timeout_t timeout = Timer::inf);
00622 
00628     bool access(timeout_t timeout = Timer::inf);
00629 
00636     static void indexing(unsigned size);
00637 
00645     static bool writer(const void *object, timeout_t timeout = Timer::inf);
00646 
00654     static bool reader(const void *object, timeout_t timeout = Timer::inf);
00655 
00660     static void release(const void *object);
00661 
00665     void release(void);
00666 };
00667 
00678 class __EXPORT ReusableAllocator : protected Conditional
00679 {
00680 protected:
00681     ReusableObject *freelist;
00682     unsigned waiting;
00683 
00687     ReusableAllocator();
00688 
00694     inline ReusableObject *next(ReusableObject *object)
00695         {return object->getNext();}
00696 
00701     void release(ReusableObject *object);
00702 };
00703 
00714 class __EXPORT ConditionalLock : protected ConditionalAccess, public SharedAccess
00715 {
00716 protected:
00717     class Context : public LinkedObject
00718     {
00719     public:
00720         inline Context(LinkedObject **root) : LinkedObject(root) {}
00721 
00722         pthread_t thread;
00723         unsigned count;
00724     };
00725 
00726     LinkedObject *contexts;
00727 
00728     virtual void _share(void);
00729     virtual void _unlock(void);
00730 
00731     Context *getContext(void);
00732 
00733 public:
00737     ConditionalLock();
00738 
00742     ~ConditionalLock();
00743 
00747     void modify(void);
00748 
00752     void commit(void);
00753 
00757     void access(void);
00758 
00762     void release(void);
00763 
00768     virtual void exclusive(void);
00769 
00773     virtual void share(void);
00774 };
00775 
00788 class __EXPORT barrier : private Conditional
00789 {
00790 private:
00791     unsigned count;
00792     unsigned waits;
00793 
00794 public:
00799     barrier(unsigned count);
00800 
00804     ~barrier();
00805 
00811     void set(unsigned count);
00812 
00816     void inc(void);
00817 
00821     void dec(void);
00822 
00827     unsigned operator++(void);
00828 
00829     unsigned operator--(void);
00830 
00834     void wait(void);
00835 
00842     bool wait(timeout_t timeout);
00843 };
00844 
00853 class __EXPORT Semaphore : public SharedAccess, protected Conditional
00854 {
00855 protected:
00856     unsigned count, waits, used;
00857 
00858     virtual void _share(void);
00859     virtual void _unlock(void);
00860 
00861 public:
00866     Semaphore(unsigned count = 0);
00867 
00873     Semaphore(unsigned count, unsigned avail);
00874 
00879     void wait(void);
00880 
00888     bool wait(timeout_t timeout);
00889 
00894     void set(unsigned count);
00895 
00899     void release(void);
00900 
00904     inline void operator++(void)
00905         {wait();}
00906 
00910     inline void operator--(void)
00911         {release();}
00912 };
00913 
00927 class __EXPORT Mutex : public ExclusiveAccess
00928 {
00929 protected:
00930     pthread_mutex_t mlock;
00931 
00932     virtual void _lock(void);
00933     virtual void _unlock(void);
00934 
00935 public:
00943     class __EXPORT guard
00944     {
00945     private:
00946         const void *object;
00947 
00948     public:
00953         guard();
00954 
00959         guard(const void *object);
00960 
00964         ~guard();
00965 
00971         void set(const void *object);
00972 
00976         void release(void);
00977 
00983         inline void operator=(void *pointer)
00984             {set(pointer);}
00985     };
00986 
00987 
00991     Mutex();
00992 
00996     ~Mutex();
00997 
01001     inline void acquire(void)
01002         {pthread_mutex_lock(&mlock);}
01003 
01007     inline void lock(void)
01008         {pthread_mutex_lock(&mlock);}
01009 
01013     inline void unlock(void)
01014         {pthread_mutex_unlock(&mlock);}
01015 
01019     inline void release(void)
01020         {pthread_mutex_unlock(&mlock);}
01021 
01026     inline static void acquire(pthread_mutex_t *lock)
01027         {pthread_mutex_lock(lock);}
01028 
01033     inline static void release(pthread_mutex_t *lock)
01034         {pthread_mutex_unlock(lock);}
01035 
01042     static void indexing(unsigned size);
01043 
01049     static void protect(const void *pointer);
01050 
01055     static void release(const void *pointer);
01056 };
01057 
01066 class __EXPORT auto_protect
01067 {
01068 private:
01069     // cannot copy...
01070     inline auto_protect(const auto_object &pointer) {}
01071 
01072 protected:
01073     const void *object;
01074 
01075     auto_protect();
01076 
01077 public:
01082     auto_protect(const void *object);
01083 
01088     ~auto_protect();
01089 
01093     void release(void);
01094 
01099     inline bool operator!() const
01100         {return object == NULL;}
01101 
01106     inline operator bool() const
01107         {return object != NULL;}
01108 
01115     void operator=(const void *object);
01116 };
01117 
01129 class __EXPORT LockedPointer
01130 {
01131 private:
01132     friend class locked_release;
01133     pthread_mutex_t mutex;
01134     ObjectProtocol *pointer;
01135 
01136 protected:
01140     LockedPointer();
01141 
01146     void replace(ObjectProtocol *object);
01147 
01152     ObjectProtocol *dup(void);
01153 
01158     inline void operator=(ObjectProtocol *object)
01159         {replace(object);}
01160 };
01161 
01170 class __EXPORT SharedObject
01171 {
01172 protected:
01173     friend class SharedPointer;
01174 
01183     virtual void commit(SharedPointer *pointer);
01184 
01185 public:
01189     virtual ~SharedObject();
01190 };
01191 
01202 class __EXPORT SharedPointer : protected ConditionalAccess
01203 {
01204 private:
01205     friend class shared_release;
01206     SharedObject *pointer;
01207 
01208 protected:
01212     SharedPointer();
01213 
01217     ~SharedPointer();
01218 
01225     void replace(SharedObject *object);
01226 
01233     SharedObject *share(void);
01234 };
01235 
01246 class __EXPORT Thread
01247 {
01248 protected:
01249 // may be used in future if we need cancelable threads...
01250 #ifdef  _MSTHREADS_
01251     HANDLE cancellor;
01252 #else
01253     void *cancellor;
01254 #endif
01255 
01256     enum {R_UNUSED} reserved;   // cancel mode?
01257     pthread_t tid;
01258     size_t stack;
01259     int priority;
01260 
01266     Thread(size_t stack = 0);
01267 
01272     void map(void);
01273 
01277     virtual bool is_active(void);
01278 
01279 public:
01286     void setPriority(void);
01287 
01292     static void yield(void);
01293 
01298     static void sleep(timeout_t timeout);
01299 
01306     static Thread *get(void);
01307 
01311     virtual void run(void) = 0;
01312 
01316     virtual ~Thread();
01317 
01326     virtual void exit(void);
01327 
01331     static void init(void);
01332 
01338     static void policy(int polid);
01339 
01344     static void concurrency(int level);
01345 
01352     static bool equal(pthread_t thread1, pthread_t thread2);
01353 
01358     static pthread_t self(void);
01359 
01360     inline operator bool()
01361         {return is_active();}
01362 
01363     inline bool operator!()
01364         {return !is_active();}
01365 
01366     inline bool isRunning(void)
01367         {return is_active();}
01368 };
01369 
01380 class __EXPORT JoinableThread : public Thread
01381 {
01382 protected:
01383 #ifdef  _MSTHREADS_
01384     HANDLE running;
01385 #else
01386     volatile bool running;
01387 #endif
01388     volatile bool joining;
01389 
01394     JoinableThread(size_t size = 0);
01395 
01400     virtual ~JoinableThread();
01401 
01407     void join(void);
01408 
01409     bool is_active(void);
01410 
01411     virtual void run(void) = 0;
01412 
01413 public:
01414 
01423     void start(int priority = 0);
01424 
01429     inline void background(void)
01430         {start(-1);}
01431 };
01432 
01440 class __EXPORT DetachedThread : public Thread
01441 {
01442 protected:
01443     bool active;
01444 
01449     DetachedThread(size_t size = 0);
01450 
01456     ~DetachedThread();
01457 
01466     void exit(void);
01467 
01468     bool is_active(void);
01469 
01470     virtual void run(void) = 0;
01471 
01472 public:
01479     void start(int priority = 0);
01480 };
01481 
01490 class __EXPORT locked_release
01491 {
01492 protected:
01493     ObjectProtocol *object; 
01498     locked_release();
01499 
01505     locked_release(const locked_release &object);
01506 
01507 public:
01513     locked_release(LockedPointer &pointer);
01514 
01519     ~locked_release();
01520 
01524     void release(void);
01525 
01531     locked_release &operator=(LockedPointer &pointer);
01532 };
01533 
01543 class __EXPORT shared_release
01544 {
01545 protected:
01546     SharedPointer *ptr; 
01551     shared_release();
01552 
01558     shared_release(const shared_release &object);
01559 
01560 public:
01565     shared_release(SharedPointer &pointer);
01566 
01572     ~shared_release();
01573 
01577     void release(void);
01578 
01583     SharedObject *get(void);
01584 
01590     shared_release &operator=(SharedPointer &pointer);
01591 };
01592 
01600 template<class T>
01601 class shared_pointer : public SharedPointer
01602 {
01603 public:
01607     inline shared_pointer() : SharedPointer() {}
01608 
01616     inline const T *dup(void)
01617         {return static_cast<const T*>(SharedPointer::share());}
01618 
01625     inline void replace(T *object)
01626         {SharedPointer::replace(object);}
01627 
01632     inline void operator=(T *object)
01633         {replace(object);}
01634 
01639     inline T *operator*()
01640         {return dup();}
01641 };
01642 
01650 template<class T>
01651 class locked_pointer : public LockedPointer
01652 {
01653 public:
01657     inline locked_pointer() : LockedPointer() {}
01658 
01664     inline T* dup(void)
01665         {return static_cast<T *>(LockedPointer::dup());}
01666 
01671     inline void replace(T *object)
01672         {LockedPointer::replace(object);}
01673 
01678     inline void operator=(T *object)
01679         {replace(object);}
01680 
01686     inline T *operator*()
01687         {return dup();}
01688 };
01689 
01695 template<class T>
01696 class locked_instance : public locked_release
01697 {
01698 public:
01702     inline locked_instance() : locked_release() {}
01703 
01708     inline locked_instance(locked_pointer<T> &pointer) : locked_release(pointer) {}
01709 
01714     inline T& operator*() const
01715         {return *(static_cast<T&>(object));}
01716 
01721     inline T* operator->() const
01722         {return static_cast<T*>(object);}
01723 
01728     inline T* get(void) const
01729         {return static_cast<T*>(object);}
01730 };
01731 
01737 template<class T>
01738 class shared_instance : public shared_release
01739 {
01740 public:
01744     inline shared_instance() : shared_release() {}
01745 
01751     inline shared_instance(shared_pointer<T> &pointer) : shared_release(pointer) {}
01752 
01756     inline const T& operator*() const
01757         {return *(static_cast<const T&>(ptr->pointer));}
01758 
01763     inline const T* operator->() const
01764         {return static_cast<const T*>(ptr->pointer);}
01765 
01770     inline const T* get(void) const
01771         {return static_cast<const T*>(ptr->pointer);}
01772 };
01773 
01780 template <class T>
01781 class mutex_pointer : public auto_protect
01782 {
01783 public:
01787     inline mutex_pointer() : auto_protect() {}
01788 
01793     inline mutex_pointer(T* object) : auto_protect(object) {}
01794 
01799     inline T& operator*() const
01800         {return *(static_cast<T&>(auto_protect::object));}
01801 
01806     inline T* operator->() const
01807         {return static_cast<T*>(auto_protect::object);}
01808 
01813     inline T* get(void) const
01814         {return static_cast<T*>(auto_protect::object);}
01815 };
01816 
01822 inline void start(JoinableThread *thread, int priority = 0)
01823     {thread->start(priority);}
01824 
01830 inline void start(DetachedThread *thread, int priority = 0)
01831     {thread->start(priority);}
01832 
01836 typedef ConditionalLock condlock_t;
01837 
01841 typedef ConditionalAccess accesslock_t;
01842 
01846 typedef TimedEvent timedevent_t;
01847 
01851 typedef Mutex mutex_t;
01852 
01856 typedef ThreadLock rwlock_t;
01857 
01861 typedef RecursiveMutex rexlock_t;
01862 
01866 typedef Semaphore semaphore_t;
01867 
01871 typedef barrier barrier_t;
01872 
01877 inline void wait(barrier_t &barrier)
01878     {barrier.wait();}
01879 
01885 inline void wait(semaphore_t &semaphore, timeout_t timeout = Timer::inf)
01886     {semaphore.wait(timeout);}
01887 
01892 inline void release(semaphore_t &semaphore)
01893     {semaphore.release();}
01894 
01899 inline void acquire(mutex_t &mutex)
01900     {mutex.lock();}
01901 
01906 inline void release(mutex_t &mutex)
01907     {mutex.release();}
01908 
01913 inline void modify(accesslock_t &lock)
01914     {lock.modify();}
01915 
01920 inline void access(accesslock_t &lock)
01921     {lock.access();}
01922 
01927 inline void release(accesslock_t &lock)
01928     {lock.release();}
01929 
01935 inline void commit(accesslock_t &lock)
01936     {lock.commit();}
01937 
01942 inline void exclusive(condlock_t &lock)
01943     {lock.exclusive();}
01944 
01949 inline void share(condlock_t &lock)
01950     {lock.share();}
01951 
01956 inline void modify(condlock_t &lock)
01957     {lock.modify();}
01958 
01964 inline void commit(condlock_t &lock)
01965     {lock.commit();}
01966 
01971 inline void access(condlock_t &lock)
01972     {lock.access();}
01973 
01978 inline void release(condlock_t &lock)
01979     {lock.release();}
01980 
01986 inline bool exclusive(rwlock_t &lock, timeout_t timeout = Timer::inf)
01987     {return lock.modify(timeout);}
01988 
01994 inline bool share(rwlock_t &lock, timeout_t timeout = Timer::inf)
01995     {return lock.access(timeout);}
01996 
02001 inline void release(rwlock_t &lock)
02002     {lock.release();}
02003 
02008 inline void lock(rexlock_t &lock)
02009     {lock.lock();}
02010 
02015 inline void release(rexlock_t &lock)
02016     {lock.release();}
02017 
02018 inline bool _sync_protect_(const void *obj)
02019 {
02020     Mutex::protect(obj);
02021     return true;
02022 }
02023 
02024 inline bool _sync_release_(const void *obj)
02025 {
02026     Mutex::release(obj);
02027     return false;
02028 }
02029 
02030 inline bool _rw_reader_(const void *obj)
02031 {
02032     ThreadLock::reader(obj);
02033     return true;
02034 }
02035 
02036 inline bool _rw_writer_(const void *obj)
02037 {
02038     ThreadLock::writer(obj);
02039     return true;
02040 }
02041 
02042 inline bool _rw_release_(const void *obj)
02043 {
02044     ThreadLock::release(obj);
02045     return false;
02046 }
02047 
02048 #define ENTER_EXCLUSIVE \
02049     do { static pthread_mutex_t __sync__ = PTHREAD_MUTEX_INITIALIZER; \
02050         pthread_mutex_lock(&__sync__);
02051 
02052 #define LEAVE_EXCLUSIVE \
02053     pthread_mutex_unlock(&__sync__);} while(0);
02054 
02055 #define SYNC(obj) for(bool _sync_flag_ = _sync_protect_(obj); _sync_flag_; _sync_flag_ = _sync_release_(obj))
02056 
02057 #define SHARED(obj) for(bool _sync_flag_ = _rw_reader_(obj); _sync_flag_; _sync_flag_ = _rw_release_(obj))
02058 
02059 #define EXCLUSIVE(obj) for(bool _sync_flag_ = _rw_writer_(obj); _sync_flag_; _sync_flag_ = _rw_release_(obj))
02060 
02061 } // namespace ucommon
02062 
02063 #endif