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:
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
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
01242 #ifdef _MSWINDOWS_
01243 HANDLE cancellor;
01244 #else
01245 void *cancellor;
01246 #endif
01247
01248 enum {} reserved;
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