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_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:
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
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
01250 #ifdef _MSWINDOWS_
01251 HANDLE cancellor;
01252 #else
01253 void *cancellor;
01254 #endif
01255
01256 enum {} reserved;
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 _MSWINDOWS_
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 END_NAMESPACE
02062
02063 #endif