00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00053 #ifndef _UCOMMON_THREAD_H_
00054 #define _UCOMMON_THREAD_H_
00055
00056 #ifndef _UCOMMON_CONFIG_H_
00057 #include <ucommon/platform.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 gettimeout(timeout_t timeout, struct timespec *hires);
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 gettimeout(timeout_t timeout, struct timespec *hires)
00260 {Conditional::gettimeout(timeout, hires);};
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
00450 inline static void signal(TimedEvent& timed)
00451 {timed.signal();};
00452
00457 inline static void reset(TimedEvent& timed)
00458 {timed.reset();};
00459
00466 inline static bool wait(TimedEvent& timed, timeout_t timeout)
00467 {return timed.wait(timeout);};
00468 };
00469
00477 class __EXPORT RecursiveMutex : private Conditional, public ExclusiveProtocol
00478 {
00479 protected:
00480 unsigned waiting;
00481 unsigned lockers;
00482 pthread_t locker;
00483
00484 void Exlock(void);
00485 void Unlock(void);
00486
00487 public:
00491 RecursiveMutex();
00492
00496 void lock(void);
00497
00501 bool lock(timeout_t timeout);
00502
00506 void release(void);
00507
00512 unsigned getLocking(void);
00513
00518 unsigned getWaiting(void);
00519
00524 inline static void lock(RecursiveMutex& rex)
00525 {rex.lock();};
00526
00531 inline static void release(RecursiveMutex& rex)
00532 {rex.release();};
00533 };
00534
00547 class __EXPORT ThreadLock : private ConditionalAccess, public ExclusiveProtocol, public SharedProtocol
00548 {
00549 protected:
00550 unsigned writers;
00551 pthread_t writeid;
00552
00553 void Exlock(void);
00554 void Shlock(void);
00555 void Unlock(void);
00556
00557 public:
00565 class __EXPORT gaurd_reader
00566 {
00567 private:
00568 void *object;
00569
00570 public:
00575 gaurd_reader();
00576
00581 gaurd_reader(void *object);
00582
00586 ~gaurd_reader();
00587
00593 void set(void *object);
00594
00598 void release(void);
00599
00605 inline void operator=(void *pointer)
00606 {set(pointer);};
00607 };
00608
00616 class __EXPORT gaurd_writer
00617 {
00618 private:
00619 void *object;
00620
00621 public:
00626 gaurd_writer();
00627
00632 gaurd_writer(void *object);
00633
00637 ~gaurd_writer();
00638
00644 void set(void *object);
00645
00649 void release(void);
00650
00656 inline void operator=(void *pointer)
00657 {set(pointer);};
00658 };
00659
00663 ThreadLock();
00664
00670 bool modify(timeout_t timeout = Timer::inf);
00671
00677 bool access(timeout_t timeout = Timer::inf);
00678
00685 static void indexing(unsigned size);
00686
00694 static bool writer(void *object, timeout_t timeout = Timer::inf);
00695
00703 static bool reader(void *object, timeout_t timeout = Timer::inf);
00704
00709 static void release(void *object);
00710
00714 void release(void);
00715
00720 unsigned getAccess(void);
00721
00726 unsigned getModify(void);
00727
00732 unsigned getWaiting(void);
00733
00740 inline static bool modify(ThreadLock& lock, timeout_t timeout = Timer::inf)
00741 {return lock.modify(timeout);};
00742
00749 inline static bool access(ThreadLock& lock, timeout_t timeout = Timer::inf)
00750 {return lock.access(timeout);};
00751
00756 inline static void release(ThreadLock& lock)
00757 {lock.release();};
00758 };
00759
00770 class __EXPORT ReusableAllocator : protected Conditional
00771 {
00772 protected:
00773 ReusableObject *freelist;
00774 unsigned waiting;
00775
00779 ReusableAllocator();
00780
00786 inline ReusableObject *next(ReusableObject *object)
00787 {return object->getNext();};
00788
00793 void release(ReusableObject *object);
00794 };
00795
00806 class __EXPORT ConditionalLock : protected ConditionalAccess, public SharedProtocol
00807 {
00808 protected:
00809 class Context : public LinkedObject
00810 {
00811 public:
00812 inline Context(LinkedObject **root) : LinkedObject(root) {};
00813
00814 pthread_t thread;
00815 unsigned count;
00816 };
00817
00818 LinkedObject *contexts;
00819
00820 void Shlock(void);
00821 void Unlock(void);
00822 void Exclusive(void);
00823 void Share(void);
00824 Context *getContext(void);
00825
00826 public:
00830 ConditionalLock();
00831
00835 ~ConditionalLock();
00836
00840 void modify(void);
00841
00845 void commit(void);
00846
00850 void access(void);
00851
00855 void release(void);
00856
00861 void exclusive(void);
00862
00866 void share(void);
00867
00871 unsigned getReaders(void);
00872
00876 unsigned getWaiters(void);
00877
00882 inline static void modify(ConditionalLock& lock)
00883 {lock.modify();};
00884
00889 inline static void commit(ConditionalLock& lock)
00890 {lock.commit();};
00891
00896 inline static void release(ConditionalLock& lock)
00897 {lock.release();};
00898
00903 inline static void access(ConditionalLock& lock)
00904 {lock.access();};
00905
00910 inline static void exclusive(ConditionalLock& lock)
00911 {lock.exclusive();};
00912
00917 inline static void share(ConditionalLock& lock)
00918 {lock.share();};
00919 };
00920
00933 class __EXPORT barrier : private Conditional
00934 {
00935 private:
00936 unsigned count;
00937 unsigned waits;
00938
00939 public:
00944 barrier(unsigned count);
00945
00949 ~barrier();
00950
00956 void set(unsigned count);
00957
00961 void inc(void);
00962
00966 void dec(void);
00967
00972 unsigned operator++(void);
00973
00974 unsigned operator--(void);
00975
00979 void wait(void);
00980
00987 bool wait(timeout_t timeout);
00988
00993 inline static void wait(barrier& sync)
00994 {sync.wait();};
00995
01002 inline static bool wait(barrier& sync, timeout_t timeout)
01003 {return sync.wait(timeout);};
01004
01005
01011 inline static void set(barrier& sync, unsigned count)
01012 {sync.set(count);};
01013 };
01014
01023 class __EXPORT Semaphore : public SharedProtocol, protected Conditional
01024 {
01025 protected:
01026 unsigned count, waits, used;
01027
01028 void Shlock(void);
01029 void Unlock(void);
01030
01031 public:
01035 Semaphore(unsigned count = 0);
01036
01041 void wait(void);
01042
01050 bool wait(timeout_t timeout);
01051
01056 unsigned getCount(void);
01057
01062 unsigned getUsed(void);
01063
01068 void set(unsigned count);
01069
01073 void release(void);
01074
01078 inline void operator++(void)
01079 {wait();};
01080
01084 inline void operator--(void)
01085 {release();};
01086
01091 inline static void wait(Semaphore& sync)
01092 {sync.wait();};
01093
01100 inline static bool wait(Semaphore& sync, timeout_t timeout)
01101 {return sync.wait(timeout);};
01102
01107 inline static void release(Semaphore& sync)
01108 {sync.release();};
01109 };
01110
01124 class __EXPORT Mutex : public ExclusiveProtocol
01125 {
01126 protected:
01127 pthread_mutex_t mlock;
01128
01129 void Exlock(void);
01130 void Unlock(void);
01131
01132 public:
01140 class __EXPORT gaurd
01141 {
01142 private:
01143 void *object;
01144
01145 public:
01150 gaurd();
01151
01156 gaurd(void *object);
01157
01161 ~gaurd();
01162
01168 void set(void *object);
01169
01173 void release(void);
01174
01180 inline void operator=(void *pointer)
01181 {set(pointer);};
01182 };
01183
01184
01188 Mutex();
01189
01193 ~Mutex();
01194
01198 inline void acquire(void)
01199 {pthread_mutex_lock(&mlock);};
01200
01204 inline void lock(void)
01205 {pthread_mutex_lock(&mlock);};
01206
01210 inline void unlock(void)
01211 {pthread_mutex_unlock(&mlock);};
01212
01216 inline void release(void)
01217 {pthread_mutex_unlock(&mlock);};
01218
01223 inline static void acquire(Mutex& lock)
01224 {pthread_mutex_lock(&lock.mlock);};
01225
01230 inline static void lock(Mutex& lock)
01231 {pthread_mutex_lock(&lock.mlock);};
01232
01237 inline static void unlock(Mutex& lock)
01238 {pthread_mutex_unlock(&lock.mlock);};
01239
01244 inline static void release(Mutex& lock)
01245 {pthread_mutex_unlock(&lock.mlock);};
01246
01251 inline static void acquire(pthread_mutex_t *lock)
01252 {pthread_mutex_lock(lock);};
01253
01258 inline static void lock(pthread_mutex_t *lock)
01259 {pthread_mutex_lock(lock);};
01260
01265 inline static void unlock(pthread_mutex_t *lock)
01266 {pthread_mutex_unlock(lock);};
01267
01272 inline static void release(pthread_mutex_t *lock)
01273 {pthread_mutex_unlock(lock);};
01274
01281 static void indexing(unsigned size);
01282
01288 static void protect(void *pointer);
01289
01294 static void release(void *pointer);
01295 };
01296
01305 class __EXPORT auto_protect
01306 {
01307 private:
01308
01309 inline auto_protect(const auto_object &pointer) {};
01310
01311 protected:
01312 void *object;
01313
01314 auto_protect();
01315
01316 public:
01321 auto_protect(void *object);
01322
01327 ~auto_protect();
01328
01332 void release(void);
01333
01338 inline bool operator!() const
01339 {return object == NULL;};
01340
01345 inline operator bool() const
01346 {return object != NULL;};
01347
01354 void operator=(void *object);
01355 };
01356
01368 class __EXPORT LockedPointer
01369 {
01370 private:
01371 friend class locked_release;
01372 pthread_mutex_t mutex;
01373 ObjectProtocol *pointer;
01374
01375 protected:
01379 LockedPointer();
01380
01385 void replace(ObjectProtocol *object);
01386
01391 ObjectProtocol *dup(void);
01392
01397 inline void operator=(ObjectProtocol *object)
01398 {replace(object);};
01399 };
01400
01409 class __EXPORT SharedObject
01410 {
01411 protected:
01412 friend class SharedPointer;
01413
01422 virtual void commit(SharedPointer *pointer);
01423
01424 public:
01428 virtual ~SharedObject();
01429 };
01430
01441 class __EXPORT SharedPointer : protected ConditionalAccess
01442 {
01443 private:
01444 friend class shared_release;
01445 SharedObject *pointer;
01446
01447 protected:
01451 SharedPointer();
01452
01456 ~SharedPointer();
01457
01464 void replace(SharedObject *object);
01465
01472 SharedObject *share(void);
01473 };
01474
01485 class __EXPORT Thread
01486 {
01487 protected:
01488
01489 #ifdef _MSWINDOWS_
01490 HANDLE cancellor;
01491 #else
01492 void *cancellor;
01493 #endif
01494
01495 enum {} reserved;
01496 pthread_t tid;
01497 size_t stack;
01498 int priority;
01499
01505 Thread(size_t stack = 0);
01506
01511 void map(void);
01512
01513 public:
01520 void setPriority(void);
01521
01526 static void yield(void);
01527
01532 static void sleep(timeout_t timeout);
01533
01540 static Thread *get(void);
01541
01545 virtual void run(void) = 0;
01546
01550 virtual ~Thread();
01551
01560 virtual void exit(void);
01561
01565 static void init(void);
01566
01572 static void policy(int polid);
01573
01578 static void concurrency(int level);
01579
01586 static bool equal(pthread_t thread1, pthread_t thread2);
01587
01592 static pthread_t self(void);
01593
01597 virtual bool isRunning(void);
01598
01599 inline operator bool()
01600 {return isRunning();}
01601 };
01602
01613 class __EXPORT JoinableThread : protected Thread
01614 {
01615 protected:
01616 #ifdef _MSWINDOWS_
01617 HANDLE running;
01618 #else
01619 volatile bool running;
01620 #endif
01621 volatile bool joining;
01622
01627 JoinableThread(size_t size = 0);
01628
01633 virtual ~JoinableThread();
01634
01640 void join(void);
01641
01642 public:
01643 bool isRunning(void);
01644
01653 void start(int priority = 0);
01654
01659 inline void background(void)
01660 {start(-1);};
01661 };
01662
01670 class __EXPORT DetachedThread : protected Thread
01671 {
01672 protected:
01673 bool active;
01674
01679 DetachedThread(size_t size = 0);
01680
01686 ~DetachedThread();
01687
01696 void exit(void);
01697
01698 public:
01705 void start(int priority = 0);
01706
01707 bool isRunning(void);
01708 };
01709
01718 class __EXPORT locked_release
01719 {
01720 protected:
01721 ObjectProtocol *object;
01726 locked_release();
01727
01733 locked_release(const locked_release &object);
01734
01735 public:
01741 locked_release(LockedPointer &pointer);
01742
01747 ~locked_release();
01748
01752 void release(void);
01753
01759 locked_release &operator=(LockedPointer &pointer);
01760 };
01761
01771 class __EXPORT shared_release
01772 {
01773 protected:
01774 SharedPointer *ptr;
01779 shared_release();
01780
01786 shared_release(const shared_release &object);
01787
01788 public:
01793 shared_release(SharedPointer &pointer);
01794
01800 ~shared_release();
01801
01805 void release(void);
01806
01811 SharedObject *get(void);
01812
01818 shared_release &operator=(SharedPointer &pointer);
01819 };
01820
01828 template<class T>
01829 class shared_pointer : public SharedPointer
01830 {
01831 public:
01835 inline shared_pointer() : SharedPointer() {};
01836
01844 inline const T *dup(void)
01845 {return static_cast<const T*>(SharedPointer::share());};
01846
01853 inline void replace(T *object)
01854 {SharedPointer::replace(object);};
01855
01860 inline void operator=(T *object)
01861 {replace(object);};
01862
01867 inline T *operator*()
01868 {return dup();};
01869 };
01870
01878 template<class T>
01879 class locked_pointer : public LockedPointer
01880 {
01881 public:
01885 inline locked_pointer() : LockedPointer() {};
01886
01892 inline T* dup(void)
01893 {return static_cast<T *>(LockedPointer::dup());};
01894
01899 inline void replace(T *object)
01900 {LockedPointer::replace(object);};
01901
01906 inline void operator=(T *object)
01907 {replace(object);};
01908
01914 inline T *operator*()
01915 {return dup();};
01916 };
01917
01923 template<class T>
01924 class locked_instance : public locked_release
01925 {
01926 public:
01930 inline locked_instance() : locked_release() {};
01931
01936 inline locked_instance(locked_pointer<T> &pointer) : locked_release(pointer) {};
01937
01942 inline T& operator*() const
01943 {return *(static_cast<T *>(object));};
01944
01949 inline T* operator->() const
01950 {return static_cast<T*>(object);};
01951
01956 inline T* get(void) const
01957 {return static_cast<T*>(object);};
01958 };
01959
01965 template<class T>
01966 class shared_instance : public shared_release
01967 {
01968 public:
01972 inline shared_instance() : shared_release() {};
01973
01979 inline shared_instance(shared_pointer<T> &pointer) : shared_release(pointer) {};
01980
01984 inline const T& operator*() const
01985 {return *(static_cast<const T *>(ptr->pointer));};
01986
01991 inline const T* operator->() const
01992 {return static_cast<const T*>(ptr->pointer);};
01993
01998 inline const T* get(void) const
01999 {return static_cast<const T*>(ptr->pointer);};
02000 };
02001
02008 template <class T>
02009 class mutex_pointer : public auto_protect
02010 {
02011 public:
02015 inline mutex_pointer() : auto_protect() {};
02016
02021 inline mutex_pointer(T* object) : auto_protect(object) {};
02022
02027 inline T& operator*() const
02028 {return *(static_cast<T*>(auto_protect::object));};
02029
02034 inline T* operator->() const
02035 {return static_cast<T*>(auto_protect::object);};
02036
02041 inline T* get(void) const
02042 {return static_cast<T*>(auto_protect::object);};
02043 };
02044
02050 inline void start(JoinableThread *thread, int priority = 0)
02051 {thread->start(priority);}
02052
02058 inline void start(DetachedThread *thread, int priority = 0)
02059 {thread->start(priority);}
02060
02064 typedef ConditionalLock condlock_t;
02065
02069 typedef ConditionalAccess accesslock_t;
02070
02074 typedef TimedEvent timedevent_t;
02075
02079 typedef Mutex mutex_t;
02080
02084 typedef ThreadLock rwlock_t;
02085
02089 typedef RecursiveMutex rexlock_t;
02090
02094 typedef Semaphore semaphore_t;
02095
02099 typedef barrier barrier_t;
02100
02105 inline void wait(barrier_t &barrier)
02106 {barrier.wait();}
02107
02113 inline void wait(semaphore_t &semaphore, timeout_t timeout = Timer::inf)
02114 {semaphore.wait(timeout);}
02115
02120 inline void release(semaphore_t &semaphore)
02121 {semaphore.release();}
02122
02127 inline void acquire(mutex_t &mutex)
02128 {mutex.lock();}
02129
02134 inline void release(mutex_t &mutex)
02135 {mutex.release();}
02136
02141 inline void modify(accesslock_t &lock)
02142 {lock.modify();}
02143
02148 inline void access(accesslock_t &lock)
02149 {lock.access();}
02150
02155 inline void release(accesslock_t &lock)
02156 {lock.release();}
02157
02163 inline void commit(accesslock_t &lock)
02164 {lock.commit();}
02165
02170 inline void exclusive(condlock_t &lock)
02171 {lock.exclusive();}
02172
02177 inline void share(condlock_t &lock)
02178 {lock.share();}
02179
02184 inline void modify(condlock_t &lock)
02185 {lock.modify();}
02186
02192 inline void commit(condlock_t &lock)
02193 {lock.commit();}
02194
02199 inline void access(condlock_t &lock)
02200 {lock.access();}
02201
02206 inline void release(condlock_t &lock)
02207 {lock.release();}
02208
02214 inline bool exclusive(rwlock_t &lock, timeout_t timeout = Timer::inf)
02215 {return lock.modify(timeout);}
02216
02222 inline bool share(rwlock_t &lock, timeout_t timeout = Timer::inf)
02223 {return lock.access(timeout);}
02224
02229 inline void release(rwlock_t &lock)
02230 {lock.release();}
02231
02236 inline void lock(rexlock_t &lock)
02237 {lock.lock();}
02238
02243 inline void release(rexlock_t &lock)
02244 {lock.release();}
02245
02246 END_NAMESPACE
02247
02248 #define ENTER_EXCLUSIVE \
02249 do { static pthread_mutex_t __sync__ = PTHREAD_MUTEX_INITIALIZER; \
02250 pthread_mutex_lock(&__sync__);
02251
02252 #define LEAVE_EXCLUSIVE \
02253 pthread_mutex_unlock(&__sync__);} while(0);
02254
02255 #endif