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 private:
00216 #if defined _MSCONDITIONAL_
00217 CONDITION_VARIABLE bcast;
00218 #elif !defined(_MSWINDOWS_)
00219 pthread_cond_t bcast;
00220 #endif
00221
00222 protected:
00223 unsigned pending, waiting, sharing;
00224
00230 bool waitSignal(timeout_t timeout);
00231
00237 bool waitBroadcast(timeout_t timeout);
00238
00239
00245 bool waitSignal(struct timespec *timeout);
00246
00252 bool waitBroadcast(struct timespec *timeout);
00253
00260 inline static void gettimeout(timeout_t timeout, struct timespec *hires)
00261 {Conditional::gettimeout(timeout, hires);};
00262
00263
00264 #ifdef _MSWINDOWS_
00265 inline void lock(void)
00266 {EnterCriticalSection(&mutex);};
00267
00268 inline void unlock(void)
00269 {LeaveCriticalSection(&mutex);};
00270
00271 void waitSignal(void);
00272 void waitBroadcast(void);
00273
00274 inline void signal(void)
00275 {Conditional::signal();};
00276
00277 inline void broadcast(void)
00278 {Conditional::broadcast();};
00279
00280 #else
00281
00284 inline void lock(void)
00285 {pthread_mutex_lock(&mutex);};
00286
00290 inline void unlock(void)
00291 {pthread_mutex_unlock(&mutex);};
00292
00296 inline void waitSignal(void)
00297 {pthread_cond_wait(&cond, &mutex);};
00298
00302 inline void waitBroadcast(void)
00303 {pthread_cond_wait(&bcast, &mutex);};
00304
00305
00309 inline void signal(void)
00310 {pthread_cond_signal(&cond);};
00311
00315 inline void broadcast(void)
00316 {pthread_cond_broadcast(&bcast);};
00317 #endif
00318 public:
00322 ConditionalAccess();
00323
00327 ~ConditionalAccess();
00328
00332 void access(void);
00333
00337 void modify(void);
00338
00342 void release(void);
00343
00347 void commit(void);
00348
00355 void limit_sharing(unsigned max);
00356 };
00357
00366 class __EXPORT TimedEvent : public Timer
00367 {
00368 private:
00369 #ifdef _MSWINDOWS_
00370 HANDLE event;
00371 #else
00372 pthread_cond_t cond;
00373 bool signalled;
00374 #endif
00375 pthread_mutex_t mutex;
00376
00377 protected:
00382 void lock(void);
00383
00388 void release(void);
00389
00397 bool sync(void);
00398
00399 public:
00403 TimedEvent(void);
00404
00409 TimedEvent(timeout_t timeout);
00410
00415 TimedEvent(time_t timeout);
00416
00420 ~TimedEvent();
00421
00427 void signal(void);
00428
00435 bool wait(timeout_t timeout);
00436
00440 void reset(void);
00441
00446 inline static void signal(TimedEvent& timed)
00447 {timed.signal();};
00448
00453 inline static void reset(TimedEvent& timed)
00454 {timed.reset();};
00455
00462 inline static bool wait(TimedEvent& timed, timeout_t timeout)
00463 {return timed.wait(timeout);};
00464 };
00465
00473 class __EXPORT rexlock : private Conditional, public Exclusive
00474 {
00475 private:
00476 unsigned waiting;
00477 unsigned lockers;
00478 pthread_t locker;
00479
00480 __LOCAL void Exlock(void);
00481 __LOCAL void Unlock(void);
00482
00483 public:
00487 rexlock();
00488
00492 void lock(void);
00493
00497 bool lock(timeout_t timeout);
00498
00502 void release(void);
00503
00508 unsigned getLocking(void);
00509
00514 unsigned getWaiting(void);
00515
00520 inline static void lock(rexlock& rex)
00521 {rex.lock();};
00522
00527 inline static void release(rexlock& rex)
00528 {rex.release();};
00529 };
00530
00543 class __EXPORT rwlock : private ConditionalAccess, public Exclusive, public Shared
00544 {
00545 private:
00546 unsigned writers;
00547 pthread_t writeid;
00548
00549 __LOCAL void Exlock(void);
00550 __LOCAL void Shlock(void);
00551 __LOCAL void Unlock(void);
00552
00553 public:
00561 class __EXPORT gaurd_reader
00562 {
00563 private:
00564 void *object;
00565
00566 public:
00571 gaurd_reader();
00572
00577 gaurd_reader(void *object);
00578
00582 ~gaurd_reader();
00583
00589 void set(void *object);
00590
00594 void release(void);
00595
00601 inline void operator=(void *pointer)
00602 {set(pointer);};
00603 };
00604
00612 class __EXPORT gaurd_writer
00613 {
00614 private:
00615 void *object;
00616
00617 public:
00622 gaurd_writer();
00623
00628 gaurd_writer(void *object);
00629
00633 ~gaurd_writer();
00634
00640 void set(void *object);
00641
00645 void release(void);
00646
00652 inline void operator=(void *pointer)
00653 {set(pointer);};
00654 };
00655
00659 rwlock();
00660
00666 bool modify(timeout_t timeout = Timer::inf);
00667
00673 bool access(timeout_t timeout = Timer::inf);
00674
00681 static void indexing(unsigned size);
00682
00690 static bool writer(void *object, timeout_t timeout = Timer::inf);
00691
00699 static bool reader(void *object, timeout_t timeout = Timer::inf);
00700
00705 static void release(void *object);
00706
00710 void release(void);
00711
00716 unsigned getAccess(void);
00717
00722 unsigned getModify(void);
00723
00728 unsigned getWaiting(void);
00729
00736 inline static bool modify(rwlock& lock, timeout_t timeout = Timer::inf)
00737 {return lock.modify(timeout);};
00738
00745 inline static bool access(rwlock& lock, timeout_t timeout = Timer::inf)
00746 {return lock.access(timeout);};
00747
00752 inline static void release(rwlock& lock)
00753 {lock.release();};
00754 };
00755
00766 class __EXPORT ReusableAllocator : protected Conditional
00767 {
00768 protected:
00769 ReusableObject *freelist;
00770 unsigned waiting;
00771
00775 ReusableAllocator();
00776
00782 inline ReusableObject *next(ReusableObject *object)
00783 {return object->getNext();};
00784
00789 void release(ReusableObject *object);
00790 };
00791
00802 class __EXPORT ConditionalLock : protected ConditionalAccess, public Shared
00803 {
00804 private:
00805 class Context : public LinkedObject
00806 {
00807 public:
00808 inline Context(LinkedObject **root) : LinkedObject(root) {};
00809
00810 pthread_t thread;
00811 unsigned count;
00812 };
00813
00814 LinkedObject *contexts;
00815
00816 __LOCAL void Shlock(void);
00817 __LOCAL void Unlock(void);
00818 __LOCAL void Exclusive(void);
00819 __LOCAL void Share(void);
00820 __LOCAL Context *getContext(void);
00821
00822 public:
00826 ConditionalLock();
00827
00831 ~ConditionalLock();
00832
00836 void modify(void);
00837
00841 void commit(void);
00842
00846 void access(void);
00847
00851 void release(void);
00852
00857 void exclusive(void);
00858
00862 void share(void);
00863
00867 unsigned getReaders(void);
00868
00872 unsigned getWaiters(void);
00873
00878 inline static void modify(ConditionalLock& lock)
00879 {lock.modify();};
00880
00885 inline static void commit(ConditionalLock& lock)
00886 {lock.commit();};
00887
00892 inline static void release(ConditionalLock& lock)
00893 {lock.release();};
00894
00899 inline static void access(ConditionalLock& lock)
00900 {lock.access();};
00901
00906 inline static void exclusive(ConditionalLock& lock)
00907 {lock.exclusive();};
00908
00913 inline static void share(ConditionalLock& lock)
00914 {lock.share();};
00915 };
00916
00929 class __EXPORT barrier : private Conditional
00930 {
00931 private:
00932 unsigned count;
00933 unsigned waits;
00934
00935 public:
00940 barrier(unsigned count);
00941
00945 ~barrier();
00946
00952 void set(unsigned count);
00953
00957 void inc(void);
00958
00962 void dec(void);
00963
00968 unsigned operator++(void);
00969
00970 unsigned operator--(void);
00971
00975 void wait(void);
00976
00983 bool wait(timeout_t timeout);
00984
00989 inline static void wait(barrier& sync)
00990 {sync.wait();};
00991
00998 inline static bool wait(barrier& sync, timeout_t timeout)
00999 {return sync.wait(timeout);};
01000
01001
01007 inline static void set(barrier& sync, unsigned count)
01008 {sync.set(count);};
01009 };
01010
01019 class __EXPORT semaphore : public Shared, private Conditional
01020 {
01021 private:
01022 unsigned count, waits, used;
01023
01024 __LOCAL void Shlock(void);
01025 __LOCAL void Unlock(void);
01026
01027 public:
01031 semaphore(unsigned count = 0);
01032
01037 void wait(void);
01038
01046 bool wait(timeout_t timeout);
01047
01052 unsigned getCount(void);
01053
01058 unsigned getUsed(void);
01059
01064 void set(unsigned count);
01065
01069 void release(void);
01070
01074 inline void operator++(void)
01075 {wait();};
01076
01080 inline void operator--(void)
01081 {release();};
01082
01087 inline static void wait(semaphore& sync)
01088 {sync.wait();};
01089
01096 inline static bool wait(semaphore& sync, timeout_t timeout)
01097 {return sync.wait(timeout);};
01098
01103 inline static void release(semaphore& sync)
01104 {sync.release();};
01105 };
01106
01120 class __EXPORT mutex : public Exclusive
01121 {
01122 private:
01123 pthread_mutex_t mlock;
01124
01125 __LOCAL void Exlock(void);
01126 __LOCAL void Unlock(void);
01127
01128 public:
01136 class __EXPORT gaurd
01137 {
01138 private:
01139 void *object;
01140
01141 public:
01146 gaurd();
01147
01152 gaurd(void *object);
01153
01157 ~gaurd();
01158
01164 void set(void *object);
01165
01169 void release(void);
01170
01176 inline void operator=(void *pointer)
01177 {set(pointer);};
01178 };
01179
01180
01184 mutex();
01185
01189 ~mutex();
01190
01194 inline void acquire(void)
01195 {pthread_mutex_lock(&mlock);};
01196
01200 inline void lock(void)
01201 {pthread_mutex_lock(&mlock);};
01202
01206 inline void unlock(void)
01207 {pthread_mutex_unlock(&mlock);};
01208
01212 inline void release(void)
01213 {pthread_mutex_unlock(&mlock);};
01214
01219 inline static void acquire(mutex& lock)
01220 {pthread_mutex_lock(&lock.mlock);};
01221
01226 inline static void lock(mutex& lock)
01227 {pthread_mutex_lock(&lock.mlock);};
01228
01233 inline static void unlock(mutex& lock)
01234 {pthread_mutex_unlock(&lock.mlock);};
01235
01240 inline static void release(mutex& lock)
01241 {pthread_mutex_unlock(&lock.mlock);};
01242
01247 inline static void acquire(pthread_mutex_t *lock)
01248 {pthread_mutex_lock(lock);};
01249
01254 inline static void lock(pthread_mutex_t *lock)
01255 {pthread_mutex_lock(lock);};
01256
01261 inline static void unlock(pthread_mutex_t *lock)
01262 {pthread_mutex_unlock(lock);};
01263
01268 inline static void release(pthread_mutex_t *lock)
01269 {pthread_mutex_unlock(lock);};
01270
01277 static void indexing(unsigned size);
01278
01284 static void protect(void *pointer);
01285
01290 static void release(void *pointer);
01291 };
01292
01301 class __EXPORT auto_protect
01302 {
01303 private:
01304
01305 inline auto_protect(const auto_object &pointer) {};
01306
01307 protected:
01308 void *object;
01309
01310 auto_protect();
01311
01312 public:
01317 auto_protect(void *object);
01318
01323 ~auto_protect();
01324
01328 void release(void);
01329
01334 inline bool operator!() const
01335 {return object == NULL;};
01336
01341 inline operator bool() const
01342 {return object != NULL;};
01343
01350 void operator=(void *object);
01351 };
01352
01364 class __EXPORT LockedPointer
01365 {
01366 private:
01367 friend class locked_release;
01368 pthread_mutex_t mutex;
01369 Object *pointer;
01370
01371 protected:
01375 LockedPointer();
01376
01381 void replace(Object *object);
01382
01387 Object *dup(void);
01388
01393 inline void operator=(Object *object)
01394 {replace(object);};
01395 };
01396
01405 class __EXPORT SharedObject
01406 {
01407 protected:
01408 friend class SharedPointer;
01409
01418 virtual void commit(SharedPointer *pointer);
01419
01420 public:
01424 virtual ~SharedObject();
01425 };
01426
01437 class __EXPORT SharedPointer : protected ConditionalAccess
01438 {
01439 private:
01440 friend class shared_release;
01441 SharedObject *pointer;
01442
01443 protected:
01447 SharedPointer();
01448
01452 ~SharedPointer();
01453
01460 void replace(SharedObject *object);
01461
01468 SharedObject *share(void);
01469 };
01470
01481 class __EXPORT Thread
01482 {
01483 protected:
01484 pthread_t tid;
01485 size_t stack;
01486 int priority;
01487
01493 Thread(size_t stack = 0);
01494
01499 void map(void);
01500
01501 public:
01508 void setPriority(void);
01509
01514 static void yield(void);
01515
01520 static void sleep(timeout_t timeout);
01521
01528 static Thread *get(void);
01529
01533 virtual void run(void) = 0;
01534
01538 virtual ~Thread();
01539
01548 virtual void exit(void);
01549
01553 static void init(void);
01554
01560 static void policy(int polid);
01561
01566 static void concurrency(int level);
01567
01574 static bool equal(pthread_t thread1, pthread_t thread2);
01575
01580 static pthread_t self(void);
01581 };
01582
01593 class __EXPORT JoinableThread : protected Thread
01594 {
01595 protected:
01596 #ifdef _MSWINDOWS_
01597 HANDLE joining;
01598 #else
01599 volatile bool running;
01600 #endif
01601
01606 JoinableThread(size_t size = 0);
01607
01612 virtual ~JoinableThread();
01613
01619 void join(void);
01620
01621 public:
01622 #ifdef _MSWINDOWS_
01623 inline bool isRunning(void)
01624 {return (joining != INVALID_HANDLE_VALUE);};
01625 #else
01626
01630 inline bool isRunning(void)
01631 {return running;};
01632 #endif
01633
01642 void start(int priority = 0);
01643
01648 inline void background(void)
01649 {start(-1);};
01650 };
01651
01659 class __EXPORT DetachedThread : protected Thread
01660 {
01661 protected:
01666 DetachedThread(size_t size = 0);
01667
01673 ~DetachedThread();
01674
01683 void exit(void);
01684
01685 public:
01692 void start(int priority = 0);
01693 };
01694
01703 class __EXPORT locked_release
01704 {
01705 protected:
01706 Object *object;
01711 locked_release();
01712
01718 locked_release(const locked_release &object);
01719
01720 public:
01726 locked_release(LockedPointer &pointer);
01727
01732 ~locked_release();
01733
01737 void release(void);
01738
01744 locked_release &operator=(LockedPointer &pointer);
01745 };
01746
01756 class __EXPORT shared_release
01757 {
01758 protected:
01759 SharedPointer *ptr;
01764 shared_release();
01765
01771 shared_release(const shared_release &object);
01772
01773 public:
01778 shared_release(SharedPointer &pointer);
01779
01785 ~shared_release();
01786
01790 void release(void);
01791
01796 SharedObject *get(void);
01797
01803 shared_release &operator=(SharedPointer &pointer);
01804 };
01805
01813 template<class T>
01814 class shared_pointer : public SharedPointer
01815 {
01816 public:
01820 inline shared_pointer() : SharedPointer() {};
01821
01829 inline const T *dup(void)
01830 {return static_cast<const T*>(SharedPointer::share());};
01831
01838 inline void replace(T *object)
01839 {SharedPointer::replace(object);};
01840
01845 inline void operator=(T *object)
01846 {replace(object);};
01847
01852 inline T *operator*()
01853 {return dup();};
01854 };
01855
01863 template<class T>
01864 class locked_pointer : public LockedPointer
01865 {
01866 public:
01870 inline locked_pointer() : LockedPointer() {};
01871
01877 inline T* dup(void)
01878 {return static_cast<T *>(LockedPointer::dup());};
01879
01884 inline void replace(T *object)
01885 {LockedPointer::replace(object);};
01886
01891 inline void operator=(T *object)
01892 {replace(object);};
01893
01899 inline T *operator*()
01900 {return dup();};
01901 };
01902
01908 template<class T>
01909 class locked_instance : public locked_release
01910 {
01911 public:
01915 inline locked_instance() : locked_release() {};
01916
01921 inline locked_instance(locked_pointer<T> &pointer) : locked_release(pointer) {};
01922
01927 inline T& operator*() const
01928 {return *(static_cast<T *>(object));};
01929
01934 inline T* operator->() const
01935 {return static_cast<T*>(object);};
01936
01941 inline T* get(void) const
01942 {return static_cast<T*>(object);};
01943 };
01944
01950 template<class T>
01951 class shared_instance : public shared_release
01952 {
01953 public:
01957 inline shared_instance() : shared_release() {};
01958
01964 inline shared_instance(shared_pointer<T> &pointer) : shared_release(pointer) {};
01965
01969 inline const T& operator*() const
01970 {return *(static_cast<const T *>(ptr->pointer));};
01971
01976 inline const T* operator->() const
01977 {return static_cast<const T*>(ptr->pointer);};
01978
01983 inline const T* get(void) const
01984 {return static_cast<const T*>(ptr->pointer);};
01985 };
01986
01993 template <class T>
01994 class mutex_pointer : public auto_protect
01995 {
01996 public:
02000 inline mutex_pointer() : auto_protect() {};
02001
02006 inline mutex_pointer(T* object) : auto_protect(object) {};
02007
02012 inline T& operator*() const
02013 {return *(static_cast<T*>(auto_protect::object));};
02014
02019 inline T* operator->() const
02020 {return static_cast<T*>(auto_protect::object);};
02021
02026 inline T* get(void) const
02027 {return static_cast<T*>(auto_protect::object);};
02028 };
02029
02035 inline void start(JoinableThread *thread, int priority = 0)
02036 {thread->start(priority);}
02037
02043 inline void start(DetachedThread *thread, int priority = 0)
02044 {thread->start(priority);}
02045
02049 typedef ConditionalLock condlock_t;
02050
02054 typedef ConditionalAccess accesslock_t;
02055
02059 typedef TimedEvent timedevent_t;
02060
02064 typedef mutex mutex_t;
02065
02070 typedef mutex Mutex;
02071
02075 typedef rwlock rwlock_t;
02076
02080 typedef rexlock rexlock_t;
02081
02085 typedef semaphore semaphore_t;
02086
02090 typedef barrier barrier_t;
02091
02096 inline void wait(barrier_t &barrier)
02097 {barrier.wait();}
02098
02104 inline void wait(semaphore_t &semaphore, timeout_t timeout = Timer::inf)
02105 {semaphore.wait(timeout);}
02106
02111 inline void release(semaphore_t &semaphore)
02112 {semaphore.release();}
02113
02118 inline void acquire(mutex_t &mutex)
02119 {mutex.lock();}
02120
02125 inline void release(mutex_t &mutex)
02126 {mutex.release();}
02127
02132 inline void modify(accesslock_t &lock)
02133 {lock.modify();}
02134
02139 inline void access(accesslock_t &lock)
02140 {lock.access();}
02141
02146 inline void release(accesslock_t &lock)
02147 {lock.release();}
02148
02154 inline void commit(accesslock_t &lock)
02155 {lock.commit();}
02156
02161 inline void exclusive(condlock_t &lock)
02162 {lock.exclusive();}
02163
02168 inline void share(condlock_t &lock)
02169 {lock.share();}
02170
02175 inline void modify(condlock_t &lock)
02176 {lock.modify();}
02177
02183 inline void commit(condlock_t &lock)
02184 {lock.commit();}
02185
02190 inline void access(condlock_t &lock)
02191 {lock.access();}
02192
02197 inline void release(condlock_t &lock)
02198 {lock.release();}
02199
02205 inline bool exclusive(rwlock_t &lock, timeout_t timeout = Timer::inf)
02206 {return lock.modify(timeout);}
02207
02213 inline bool share(rwlock_t &lock, timeout_t timeout = Timer::inf)
02214 {return lock.access(timeout);}
02215
02220 inline void release(rwlock_t &lock)
02221 {lock.release();}
02222
02227 inline void lock(rexlock_t &lock)
02228 {lock.lock();}
02229
02234 inline void release(rexlock_t &lock)
02235 {lock.release();}
02236
02237 END_NAMESPACE
02238
02239 #define ENTER_EXCLUSIVE \
02240 do { static pthread_mutex_t __sync__ = PTHREAD_MUTEX_INITIALIZER; \
02241 pthread_mutex_lock(&__sync__);
02242
02243 #define LEAVE_EXCLUSIVE \
02244 pthread_mutex_unlock(&__sync__);} while(0);
02245
02246 #endif