ucommon/thread.h

Go to the documentation of this file.
00001 // Copyright (C) 2006-2010 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(_MSWINDOWS_)
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  _MSWINDOWS_
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(_MSWINDOWS_) && !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(_MSWINDOWS_)
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  _MSWINDOWS_
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 _MSWINDOWS_
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:
00865     Semaphore(unsigned count = 0);
00866 
00871     void wait(void);
00872 
00880     bool wait(timeout_t timeout);
00881 
00886     void set(unsigned count);
00887 
00891     void release(void);
00892 
00896     inline void operator++(void)
00897         {wait();};
00898 
00902     inline void operator--(void)
00903         {release();};
00904 };
00905 
00919 class __EXPORT Mutex : public ExclusiveAccess
00920 {
00921 protected:
00922     pthread_mutex_t mlock;
00923 
00924     virtual void _lock(void);
00925     virtual void _unlock(void);
00926 
00927 public:
00935     class __EXPORT guard
00936     {
00937     private:
00938         const void *object;
00939 
00940     public:
00945         guard();
00946 
00951         guard(const void *object);
00952 
00956         ~guard();
00957 
00963         void set(const void *object);
00964 
00968         void release(void);
00969 
00975         inline void operator=(void *pointer)
00976             {set(pointer);};
00977     };
00978 
00979 
00983     Mutex();
00984 
00988     ~Mutex();
00989 
00993     inline void acquire(void)
00994         {pthread_mutex_lock(&mlock);};
00995 
00999     inline void lock(void)
01000         {pthread_mutex_lock(&mlock);};
01001 
01005     inline void unlock(void)
01006         {pthread_mutex_unlock(&mlock);};
01007 
01011     inline void release(void)
01012         {pthread_mutex_unlock(&mlock);};
01013 
01018     inline static void acquire(pthread_mutex_t *lock)
01019         {pthread_mutex_lock(lock);};
01020 
01025     inline static void release(pthread_mutex_t *lock)
01026         {pthread_mutex_unlock(lock);};
01027 
01034     static void indexing(unsigned size);
01035 
01041     static void protect(const void *pointer);
01042 
01047     static void release(const void *pointer);
01048 };
01049 
01058 class __EXPORT auto_protect
01059 {
01060 private:
01061     // cannot copy...
01062     inline auto_protect(const auto_object &pointer) {};
01063 
01064 protected:
01065     const void *object;
01066 
01067     auto_protect();
01068 
01069 public:
01074     auto_protect(const void *object);
01075 
01080     ~auto_protect();
01081 
01085     void release(void);
01086 
01091     inline bool operator!() const
01092         {return object == NULL;};
01093 
01098     inline operator bool() const
01099         {return object != NULL;};
01100 
01107     void operator=(const void *object);
01108 };
01109 
01121 class __EXPORT LockedPointer
01122 {
01123 private:
01124     friend class locked_release;
01125     pthread_mutex_t mutex;
01126     ObjectProtocol *pointer;
01127 
01128 protected:
01132     LockedPointer();
01133 
01138     void replace(ObjectProtocol *object);
01139 
01144     ObjectProtocol *dup(void);
01145 
01150     inline void operator=(ObjectProtocol *object)
01151         {replace(object);};
01152 };
01153 
01162 class __EXPORT SharedObject
01163 {
01164 protected:
01165     friend class SharedPointer;
01166 
01175     virtual void commit(SharedPointer *pointer);
01176 
01177 public:
01181     virtual ~SharedObject();
01182 };
01183 
01194 class __EXPORT SharedPointer : protected ConditionalAccess
01195 {
01196 private:
01197     friend class shared_release;
01198     SharedObject *pointer;
01199 
01200 protected:
01204     SharedPointer();
01205 
01209     ~SharedPointer();
01210 
01217     void replace(SharedObject *object);
01218 
01225     SharedObject *share(void);
01226 };
01227 
01238 class __EXPORT Thread
01239 {
01240 protected:
01241 // may be used in future if we need cancelable threads...
01242 #ifdef  _MSWINDOWS_
01243     HANDLE cancellor;
01244 #else
01245     void *cancellor;
01246 #endif
01247 
01248     enum {} reserved;   // cancel mode?
01249     pthread_t tid;
01250     size_t stack;
01251     int priority;
01252 
01258     Thread(size_t stack = 0);
01259 
01264     void map(void);
01265 
01269     virtual bool is_active(void);
01270 
01271 public:
01278     void setPriority(void);
01279 
01284     static void yield(void);
01285 
01290     static void sleep(timeout_t timeout);
01291 
01298     static Thread *get(void);
01299 
01303     virtual void run(void) = 0;
01304 
01308     virtual ~Thread();
01309 
01318     virtual void exit(void);
01319 
01323     static void init(void);
01324 
01330     static void policy(int polid);
01331 
01336     static void concurrency(int level);
01337 
01344     static bool equal(pthread_t thread1, pthread_t thread2);
01345 
01350     static pthread_t self(void);
01351 
01352     inline operator bool()
01353         {return is_active();}
01354 
01355     inline bool operator!()
01356         {return !is_active();}
01357 
01358     inline bool isRunning(void)
01359         {return is_active();}
01360 };
01361 
01372 class __EXPORT JoinableThread : public Thread
01373 {
01374 protected:
01375 #ifdef  _MSWINDOWS_
01376     HANDLE running;
01377 #else
01378     volatile bool running;
01379 #endif
01380     volatile bool joining;
01381 
01386     JoinableThread(size_t size = 0);
01387 
01392     virtual ~JoinableThread();
01393 
01399     void join(void);
01400 
01401     bool is_active(void);
01402 
01403     virtual void run(void) = 0;
01404 
01405 public:
01406 
01415     void start(int priority = 0);
01416 
01421     inline void background(void)
01422         {start(-1);};
01423 };
01424 
01432 class __EXPORT DetachedThread : public Thread
01433 {
01434 protected:
01435     bool active;
01436 
01441     DetachedThread(size_t size = 0);
01442 
01448     ~DetachedThread();
01449 
01458     void exit(void);
01459 
01460     bool is_active(void);
01461 
01462     virtual void run(void) = 0;
01463 
01464 public:
01471     void start(int priority = 0);
01472 };
01473 
01482 class __EXPORT locked_release
01483 {
01484 protected:
01485     ObjectProtocol *object; 
01490     locked_release();
01491 
01497     locked_release(const locked_release &object);
01498 
01499 public:
01505     locked_release(LockedPointer &pointer);
01506 
01511     ~locked_release();
01512 
01516     void release(void);
01517 
01523     locked_release &operator=(LockedPointer &pointer);
01524 };
01525 
01535 class __EXPORT shared_release
01536 {
01537 protected:
01538     SharedPointer *ptr; 
01543     shared_release();
01544 
01550     shared_release(const shared_release &object);
01551 
01552 public:
01557     shared_release(SharedPointer &pointer);
01558 
01564     ~shared_release();
01565 
01569     void release(void);
01570 
01575     SharedObject *get(void);
01576 
01582     shared_release &operator=(SharedPointer &pointer);
01583 };
01584 
01592 template<class T>
01593 class shared_pointer : public SharedPointer
01594 {
01595 public:
01599     inline shared_pointer() : SharedPointer() {};
01600 
01608     inline const T *dup(void)
01609         {return static_cast<const T*>(SharedPointer::share());};
01610 
01617     inline void replace(T *object)
01618         {SharedPointer::replace(object);};
01619 
01624     inline void operator=(T *object)
01625         {replace(object);};
01626 
01631     inline T *operator*()
01632         {return dup();};
01633 };
01634 
01642 template<class T>
01643 class locked_pointer : public LockedPointer
01644 {
01645 public:
01649     inline locked_pointer() : LockedPointer() {};
01650 
01656     inline T* dup(void)
01657         {return static_cast<T *>(LockedPointer::dup());};
01658 
01663     inline void replace(T *object)
01664         {LockedPointer::replace(object);};
01665 
01670     inline void operator=(T *object)
01671         {replace(object);};
01672 
01678     inline T *operator*()
01679         {return dup();};
01680 };
01681 
01687 template<class T>
01688 class locked_instance : public locked_release
01689 {
01690 public:
01694     inline locked_instance() : locked_release() {};
01695 
01700     inline locked_instance(locked_pointer<T> &pointer) : locked_release(pointer) {};
01701 
01706     inline T& operator*() const
01707         {return *(static_cast<T&>(object));};
01708 
01713     inline T* operator->() const
01714         {return static_cast<T*>(object);};
01715 
01720     inline T* get(void) const
01721         {return static_cast<T*>(object);};
01722 };
01723 
01729 template<class T>
01730 class shared_instance : public shared_release
01731 {
01732 public:
01736     inline shared_instance() : shared_release() {};
01737 
01743     inline shared_instance(shared_pointer<T> &pointer) : shared_release(pointer) {};
01744 
01748     inline const T& operator*() const
01749         {return *(static_cast<const T&>(ptr->pointer));};
01750 
01755     inline const T* operator->() const
01756         {return static_cast<const T*>(ptr->pointer);};
01757 
01762     inline const T* get(void) const
01763         {return static_cast<const T*>(ptr->pointer);};
01764 };
01765 
01772 template <class T>
01773 class mutex_pointer : public auto_protect
01774 {
01775 public:
01779     inline mutex_pointer() : auto_protect() {};
01780 
01785     inline mutex_pointer(T* object) : auto_protect(object) {};
01786 
01791     inline T& operator*() const
01792         {return *(static_cast<T&>(auto_protect::object));};
01793 
01798     inline T* operator->() const
01799         {return static_cast<T*>(auto_protect::object);};
01800 
01805     inline T* get(void) const
01806         {return static_cast<T*>(auto_protect::object);};
01807 };
01808 
01814 inline void start(JoinableThread *thread, int priority = 0)
01815     {thread->start(priority);}
01816 
01822 inline void start(DetachedThread *thread, int priority = 0)
01823     {thread->start(priority);}
01824 
01828 typedef ConditionalLock condlock_t;
01829 
01833 typedef ConditionalAccess accesslock_t;
01834 
01838 typedef TimedEvent timedevent_t;
01839 
01843 typedef Mutex mutex_t;
01844 
01848 typedef ThreadLock rwlock_t;
01849 
01853 typedef RecursiveMutex rexlock_t;
01854 
01858 typedef Semaphore semaphore_t;
01859 
01863 typedef barrier barrier_t;
01864 
01869 inline void wait(barrier_t &barrier)
01870     {barrier.wait();}
01871 
01877 inline void wait(semaphore_t &semaphore, timeout_t timeout = Timer::inf)
01878     {semaphore.wait(timeout);}
01879 
01884 inline void release(semaphore_t &semaphore)
01885     {semaphore.release();}
01886 
01891 inline void acquire(mutex_t &mutex)
01892     {mutex.lock();}
01893 
01898 inline void release(mutex_t &mutex)
01899     {mutex.release();}
01900 
01905 inline void modify(accesslock_t &lock)
01906     {lock.modify();}
01907 
01912 inline void access(accesslock_t &lock)
01913     {lock.access();}
01914 
01919 inline void release(accesslock_t &lock)
01920     {lock.release();}
01921 
01927 inline void commit(accesslock_t &lock)
01928     {lock.commit();}
01929 
01934 inline void exclusive(condlock_t &lock)
01935     {lock.exclusive();}
01936 
01941 inline void share(condlock_t &lock)
01942     {lock.share();}
01943 
01948 inline void modify(condlock_t &lock)
01949     {lock.modify();}
01950 
01956 inline void commit(condlock_t &lock)
01957     {lock.commit();}
01958 
01963 inline void access(condlock_t &lock)
01964     {lock.access();}
01965 
01970 inline void release(condlock_t &lock)
01971     {lock.release();}
01972 
01978 inline bool exclusive(rwlock_t &lock, timeout_t timeout = Timer::inf)
01979     {return lock.modify(timeout);}
01980 
01986 inline bool share(rwlock_t &lock, timeout_t timeout = Timer::inf)
01987     {return lock.access(timeout);}
01988 
01993 inline void release(rwlock_t &lock)
01994     {lock.release();}
01995 
02000 inline void lock(rexlock_t &lock)
02001     {lock.lock();}
02002 
02007 inline void release(rexlock_t &lock)
02008     {lock.release();}
02009 
02010 inline bool _sync_protect_(const void *obj)
02011 {
02012     Mutex::protect(obj);
02013     return true;
02014 }
02015 
02016 inline bool _sync_release_(const void *obj)
02017 {
02018     Mutex::release(obj);
02019     return false;
02020 }
02021 
02022 inline bool _rw_reader_(const void *obj)
02023 {
02024     ThreadLock::reader(obj);
02025     return true;
02026 }
02027 
02028 inline bool _rw_writer_(const void *obj)
02029 {
02030     ThreadLock::writer(obj);
02031     return true;
02032 }
02033 
02034 inline bool _rw_release_(const void *obj)
02035 {
02036     ThreadLock::release(obj);
02037     return false;
02038 }
02039 
02040 #define ENTER_EXCLUSIVE \
02041     do { static pthread_mutex_t __sync__ = PTHREAD_MUTEX_INITIALIZER; \
02042         pthread_mutex_lock(&__sync__);
02043 
02044 #define LEAVE_EXCLUSIVE \
02045     pthread_mutex_unlock(&__sync__);} while(0);
02046 
02047 #define SYNC(obj) for(bool _sync_flag_ = _sync_protect_(obj); _sync_flag_; _sync_flag_ = _sync_release_(obj))
02048 
02049 #define SHARED(obj) for(bool _sync_flag_ = _rw_reader_(obj); _sync_flag_; _sync_flag_ = _rw_release_(obj))
02050 
02051 #define EXCLUSIVE(obj) for(bool _sync_flag_ = _rw_writer_(obj); _sync_flag_; _sync_flag_ = _rw_release_(obj))
02052 
02053 END_NAMESPACE
02054 
02055 #endif

Generated on 14 Aug 2013 for UCommon by  doxygen 1.4.7