UCommon
|
00001 // Copyright (C) 2006-2014 David Sugar, Tycho Softworks. 00002 // Copyright (C) 2015 Cherokees of Idaho. 00003 // 00004 // This file is part of GNU uCommon C++. 00005 // 00006 // GNU uCommon C++ is free software: you can redistribute it and/or modify 00007 // it under the terms of the GNU Lesser General Public License as published 00008 // by the Free Software Foundation, either version 3 of the License, or 00009 // (at your option) any later version. 00010 // 00011 // GNU uCommon C++ is distributed in the hope that it will be useful, 00012 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00014 // GNU Lesser General Public License for more details. 00015 // 00016 // You should have received a copy of the GNU Lesser General Public License 00017 // along with GNU uCommon C++. If not, see <http://www.gnu.org/licenses/>. 00018 00054 #ifndef _UCOMMON_THREAD_H_ 00055 #define _UCOMMON_THREAD_H_ 00056 00057 #ifndef _UCOMMON_CPR_H_ 00058 #include <ucommon/cpr.h> 00059 #endif 00060 00061 #ifndef _UCOMMON_ACCESS_H_ 00062 #include <ucommon/access.h> 00063 #endif 00064 00065 #ifndef _UCOMMON_TIMERS_H_ 00066 #include <ucommon/timers.h> 00067 #endif 00068 00069 #ifndef _UCOMMON_MEMORY_H_ 00070 #include <ucommon/memory.h> 00071 #endif 00072 00073 namespace ucommon { 00074 00075 class SharedPointer; 00076 00087 class __EXPORT Conditional 00088 { 00089 private: 00090 friend class ConditionalAccess; 00091 00092 #if defined(_MSCONDITIONAL_) 00093 mutable CRITICAL_SECTION mutex; 00094 mutable CONDITION_VARIABLE cond; 00095 #elif defined(_MSTHREADS_) 00096 enum {SIGNAL = 0, BROADCAST = 1}; 00097 HANDLE events[2]; 00098 unsigned waiting; 00099 mutable CRITICAL_SECTION mlock; 00100 mutable CRITICAL_SECTION mutex; 00101 #else 00102 #ifndef __PTH__ 00103 class __LOCAL attribute 00104 { 00105 public: 00106 pthread_condattr_t attr; 00107 attribute(); 00108 }; 00109 00110 __LOCAL static attribute attr; 00111 #endif 00112 00113 mutable pthread_cond_t cond; 00114 mutable pthread_mutex_t mutex; 00115 #endif 00116 00117 protected: 00118 friend class TimedEvent; 00119 00125 bool wait(timeout_t timeout); 00126 00132 bool wait(struct timespec *timeout); 00133 00134 #ifdef _MSTHREADS_ 00135 inline void lock(void) 00136 {EnterCriticalSection(&mutex);}; 00137 00138 inline void unlock(void) 00139 {LeaveCriticalSection(&mutex);}; 00140 00141 void wait(void); 00142 void signal(void); 00143 void broadcast(void); 00144 00145 #else 00146 00149 inline void lock(void) 00150 {pthread_mutex_lock(&mutex);} 00151 00155 inline void unlock(void) 00156 {pthread_mutex_unlock(&mutex);} 00157 00161 inline void wait(void) 00162 {pthread_cond_wait(&cond, &mutex);} 00163 00167 inline void signal(void) 00168 {pthread_cond_signal(&cond);} 00169 00173 inline void broadcast(void) 00174 {pthread_cond_broadcast(&cond);} 00175 #endif 00176 00180 Conditional(); 00181 00185 ~Conditional(); 00186 00187 public: 00188 friend class autolock; 00189 00190 class __EXPORT autolock 00191 { 00192 private: 00193 #ifdef _MSTHREADS_ 00194 CRITICAL_SECTION *mutex; 00195 #else 00196 pthread_mutex_t *mutex; 00197 #endif 00198 00199 public: 00200 inline autolock(const Conditional* object) { 00201 mutex = &object->mutex; 00202 #ifdef _MSTHREADS_ 00203 EnterCriticalSection(mutex); 00204 #else 00205 pthread_mutex_lock(mutex); 00206 #endif 00207 } 00208 00209 inline ~autolock() { 00210 #ifdef _MSTHREADS_ 00211 LeaveCriticalSection(mutex); 00212 #else 00213 pthread_mutex_unlock(mutex); 00214 #endif 00215 } 00216 }; 00217 00218 #if !defined(_MSTHREADS_) && !defined(__PTH__) 00219 00224 static inline pthread_condattr_t *initializer(void) 00225 {return &attr.attr;} 00226 #endif 00227 00234 static void set(struct timespec *hires, timeout_t timeout); 00235 }; 00236 00244 class __EXPORT ConditionalAccess : private Conditional 00245 { 00246 protected: 00247 #if defined _MSCONDITIONAL_ 00248 CONDITION_VARIABLE bcast; 00249 #elif !defined(_MSTHREADS_) 00250 mutable pthread_cond_t bcast; 00251 #endif 00252 00253 unsigned pending, waiting, sharing; 00254 00260 bool waitSignal(timeout_t timeout); 00261 00267 bool waitBroadcast(timeout_t timeout); 00268 00269 00275 bool waitSignal(struct timespec *timeout); 00276 00282 bool waitBroadcast(struct timespec *timeout); 00283 00290 inline static void set(struct timespec *hires, timeout_t timeout) 00291 {Conditional::set(hires, timeout);} 00292 00293 00294 #ifdef _MSTHREADS_ 00295 inline void lock(void) 00296 {EnterCriticalSection(&mutex);}; 00297 00298 inline void unlock(void) 00299 {LeaveCriticalSection(&mutex);}; 00300 00301 void waitSignal(void); 00302 void waitBroadcast(void); 00303 00304 inline void signal(void) 00305 {Conditional::signal();}; 00306 00307 inline void broadcast(void) 00308 {Conditional::broadcast();}; 00309 00310 #else 00311 00314 inline void lock(void) 00315 {pthread_mutex_lock(&mutex);} 00316 00320 inline void unlock(void) 00321 {pthread_mutex_unlock(&mutex);} 00322 00326 inline void waitSignal(void) 00327 {pthread_cond_wait(&cond, &mutex);} 00328 00332 inline void waitBroadcast(void) 00333 {pthread_cond_wait(&bcast, &mutex);} 00334 00335 00339 inline void signal(void) 00340 {pthread_cond_signal(&cond);} 00341 00345 inline void broadcast(void) 00346 {pthread_cond_broadcast(&bcast);} 00347 #endif 00348 public: 00352 ConditionalAccess(); 00353 00357 ~ConditionalAccess(); 00358 00362 void access(void); 00363 00367 void modify(void); 00368 00372 void release(void); 00373 00377 void commit(void); 00378 00385 void limit_sharing(unsigned max); 00386 }; 00387 00396 class __EXPORT TimedEvent : public Timer 00397 { 00398 private: 00399 #ifdef _MSTHREADS_ 00400 HANDLE event; 00401 #else 00402 mutable pthread_cond_t cond; 00403 bool signalled; 00404 #endif 00405 mutable pthread_mutex_t mutex; 00406 00407 protected: 00412 void lock(void); 00413 00418 void release(void); 00419 00427 bool sync(void); 00428 00429 public: 00433 TimedEvent(void); 00434 00439 TimedEvent(timeout_t timeout); 00440 00445 TimedEvent(time_t timeout); 00446 00450 ~TimedEvent(); 00451 00457 void signal(void); 00458 00465 bool wait(timeout_t timeout); 00466 00470 void wait(void); 00471 00475 void reset(void); 00476 }; 00477 00485 class __EXPORT RecursiveMutex : private Conditional, public ExclusiveAccess 00486 { 00487 protected: 00488 unsigned waiting; 00489 unsigned lockers; 00490 pthread_t locker; 00491 00492 virtual void _lock(void); 00493 virtual void _unlock(void); 00494 00495 public: 00499 RecursiveMutex(); 00500 00504 void lock(void); 00505 00509 bool lock(timeout_t timeout); 00510 00514 void release(void); 00515 }; 00516 00529 class __EXPORT ThreadLock : private ConditionalAccess, public ExclusiveAccess, public SharedAccess 00530 { 00531 protected: 00532 unsigned writers; 00533 pthread_t writeid; 00534 00535 virtual void _lock(void); 00536 virtual void _share(void); 00537 virtual void _unlock(void); 00538 00539 public: 00547 class __EXPORT guard_reader 00548 { 00549 private: 00550 const void *object; 00551 00552 public: 00557 guard_reader(); 00558 00563 guard_reader(const void *object); 00564 00568 ~guard_reader(); 00569 00575 void set(const void *object); 00576 00580 void release(void); 00581 00587 inline void operator=(const void *pointer) 00588 {set(pointer);} 00589 }; 00590 00598 class __EXPORT guard_writer 00599 { 00600 private: 00601 const void *object; 00602 00603 public: 00608 guard_writer(); 00609 00614 guard_writer(const void *object); 00615 00619 ~guard_writer(); 00620 00626 void set(const void *object); 00627 00631 void release(void); 00632 00638 inline void operator=(const void *pointer) 00639 {set(pointer);} 00640 }; 00641 00645 ThreadLock(); 00646 00652 bool modify(timeout_t timeout = Timer::inf); 00653 00659 bool access(timeout_t timeout = Timer::inf); 00660 00667 static void indexing(unsigned size); 00668 00676 static bool writer(const void *object, timeout_t timeout = Timer::inf); 00677 00685 static bool reader(const void *object, timeout_t timeout = Timer::inf); 00686 00691 static bool release(const void *object); 00692 00696 void release(void); 00697 }; 00698 00709 class __EXPORT ReusableAllocator : protected Conditional 00710 { 00711 protected: 00712 ReusableObject *freelist; 00713 unsigned waiting; 00714 00718 ReusableAllocator(); 00719 00725 inline ReusableObject *next(ReusableObject *object) 00726 {return object->getNext();} 00727 00732 void release(ReusableObject *object); 00733 }; 00734 00745 class __EXPORT ConditionalLock : protected ConditionalAccess, public SharedAccess 00746 { 00747 protected: 00748 class Context : public LinkedObject 00749 { 00750 public: 00751 inline Context(LinkedObject **root) : LinkedObject(root) {} 00752 00753 pthread_t thread; 00754 unsigned count; 00755 }; 00756 00757 LinkedObject *contexts; 00758 00759 virtual void _share(void); 00760 virtual void _unlock(void); 00761 00762 Context *getContext(void); 00763 00764 public: 00768 ConditionalLock(); 00769 00773 ~ConditionalLock(); 00774 00778 void modify(void); 00779 00783 void commit(void); 00784 00788 void access(void); 00789 00793 void release(void); 00794 00799 virtual void exclusive(void); 00800 00804 virtual void share(void); 00805 }; 00806 00819 class __EXPORT barrier : private Conditional 00820 { 00821 private: 00822 unsigned count; 00823 unsigned waits; 00824 00825 public: 00830 barrier(unsigned count); 00831 00835 ~barrier(); 00836 00842 void set(unsigned count); 00843 00847 void inc(void); 00848 00852 void dec(void); 00853 00858 unsigned operator++(void); 00859 00860 unsigned operator--(void); 00861 00865 void wait(void); 00866 00873 bool wait(timeout_t timeout); 00874 }; 00875 00884 class __EXPORT Semaphore : public SharedAccess, protected Conditional 00885 { 00886 protected: 00887 unsigned count, waits, used; 00888 00889 virtual void _share(void); 00890 virtual void _unlock(void); 00891 00892 public: 00897 Semaphore(unsigned count = 0); 00898 00904 Semaphore(unsigned count, unsigned avail); 00905 00910 void wait(void); 00911 00919 bool wait(timeout_t timeout); 00920 00925 void set(unsigned count); 00926 00930 void release(void); 00931 00935 inline void operator++(void) 00936 {wait();} 00937 00941 inline void operator--(void) 00942 {release();} 00943 }; 00944 00958 class __EXPORT Mutex : public ExclusiveAccess 00959 { 00960 protected: 00961 mutable pthread_mutex_t mlock; 00962 00963 virtual void _lock(void); 00964 virtual void _unlock(void); 00965 00966 public: 00967 friend class autolock; 00968 00969 class __EXPORT autolock 00970 { 00971 private: 00972 pthread_mutex_t *mutex; 00973 00974 public: 00975 inline autolock(const Mutex *object) { 00976 mutex = &object->mlock; 00977 pthread_mutex_lock(this->mutex); 00978 } 00979 00980 inline ~autolock() { 00981 pthread_mutex_unlock(this->mutex); 00982 } 00983 }; 00984 00992 class __EXPORT guard 00993 { 00994 private: 00995 const void *object; 00996 00997 public: 01002 guard(); 01003 01008 guard(const void *object); 01009 01013 ~guard(); 01014 01020 void set(const void *object); 01021 01025 void release(void); 01026 01032 inline void operator=(void *pointer) 01033 {set(pointer);} 01034 }; 01035 01036 01040 Mutex(); 01041 01045 ~Mutex(); 01046 01050 inline void acquire(void) 01051 {pthread_mutex_lock(&mlock);} 01052 01056 inline void lock(void) 01057 {pthread_mutex_lock(&mlock);} 01058 01062 inline void unlock(void) 01063 {pthread_mutex_unlock(&mlock);} 01064 01068 inline void release(void) 01069 {pthread_mutex_unlock(&mlock);} 01070 01075 inline static void acquire(pthread_mutex_t *lock) 01076 {pthread_mutex_lock(lock);} 01077 01082 inline static void release(pthread_mutex_t *lock) 01083 {pthread_mutex_unlock(lock);} 01084 01091 static void indexing(unsigned size); 01092 01098 static bool protect(const void *pointer); 01099 01104 static bool release(const void *pointer); 01105 }; 01106 01115 class __EXPORT auto_protect 01116 { 01117 private: 01118 // cannot copy... 01119 inline auto_protect(const auto_object &pointer) {} 01120 01121 protected: 01122 const void *object; 01123 01124 auto_protect(); 01125 01126 public: 01131 auto_protect(const void *object); 01132 01137 ~auto_protect(); 01138 01142 void release(void); 01143 01148 inline bool operator!() const 01149 {return object == NULL;} 01150 01155 inline operator bool() const 01156 {return object != NULL;} 01157 01164 void operator=(const void *object); 01165 }; 01166 01178 class __EXPORT LockedPointer 01179 { 01180 private: 01181 friend class locked_release; 01182 mutable pthread_mutex_t mutex; 01183 ObjectProtocol *pointer; 01184 01185 protected: 01189 LockedPointer(); 01190 01195 void replace(ObjectProtocol *object); 01196 01201 ObjectProtocol *dup(void); 01202 01207 inline void operator=(ObjectProtocol *object) 01208 {replace(object);} 01209 }; 01210 01219 class __EXPORT SharedObject 01220 { 01221 protected: 01222 friend class SharedPointer; 01223 01232 virtual void commit(SharedPointer *pointer); 01233 01234 public: 01238 virtual ~SharedObject(); 01239 }; 01240 01251 class __EXPORT SharedPointer : protected ConditionalAccess 01252 { 01253 private: 01254 friend class shared_release; 01255 SharedObject *pointer; 01256 01257 protected: 01261 SharedPointer(); 01262 01266 ~SharedPointer(); 01267 01274 void replace(SharedObject *object); 01275 01282 SharedObject *share(void); 01283 }; 01284 01295 class __EXPORT Thread 01296 { 01297 protected: 01298 // may be used in future if we need cancelable threads... 01299 #ifdef _MSTHREADS_ 01300 HANDLE cancellor; 01301 #else 01302 void *cancellor; 01303 #endif 01304 01305 enum {R_UNUSED} reserved; // cancel mode? 01306 pthread_t tid; 01307 size_t stack; 01308 int priority; 01309 01315 Thread(size_t stack = 0); 01316 01321 void map(void); 01322 01326 virtual bool is_active(void) const; 01327 01328 public: 01335 void setPriority(void); 01336 01341 static void yield(void); 01342 01347 static void sleep(timeout_t timeout); 01348 01355 static Thread *get(void); 01356 01360 virtual void run(void) = 0; 01361 01365 virtual ~Thread(); 01366 01375 virtual void exit(void); 01376 01380 static void init(void); 01381 01387 static void policy(int polid); 01388 01393 static void concurrency(int level); 01394 01401 static bool equal(pthread_t thread1, pthread_t thread2); 01402 01407 static pthread_t self(void); 01408 01409 inline operator bool() const 01410 {return is_active();} 01411 01412 inline bool operator!() const 01413 {return !is_active();} 01414 01415 inline bool isRunning(void) const 01416 {return is_active();} 01417 }; 01418 01429 class __EXPORT JoinableThread : public Thread 01430 { 01431 protected: 01432 #ifdef _MSTHREADS_ 01433 HANDLE running; 01434 #else 01435 volatile bool running; 01436 #endif 01437 volatile bool joining; 01438 01443 JoinableThread(size_t size = 0); 01444 01449 virtual ~JoinableThread(); 01450 01456 void join(void); 01457 01458 bool is_active(void) const; 01459 01460 virtual void run(void) = 0; 01461 01462 public: 01463 01472 void start(int priority = 0); 01473 01478 inline void background(void) 01479 {start(-1);} 01480 }; 01481 01489 class __EXPORT DetachedThread : public Thread 01490 { 01491 protected: 01492 bool active; 01493 01498 DetachedThread(size_t size = 0); 01499 01505 ~DetachedThread(); 01506 01515 void exit(void); 01516 01517 bool is_active(void) const; 01518 01519 virtual void run(void) = 0; 01520 01521 public: 01528 void start(int priority = 0); 01529 }; 01530 01539 class __EXPORT locked_release 01540 { 01541 protected: 01542 ObjectProtocol *object; 01547 locked_release(); 01548 01554 locked_release(const locked_release &object); 01555 01556 public: 01562 locked_release(LockedPointer &pointer); 01563 01568 ~locked_release(); 01569 01573 void release(void); 01574 01580 locked_release &operator=(LockedPointer &pointer); 01581 }; 01582 01592 class __EXPORT shared_release 01593 { 01594 protected: 01595 SharedPointer *ptr; 01600 shared_release(); 01601 01607 shared_release(const shared_release &object); 01608 01609 public: 01614 shared_release(SharedPointer &pointer); 01615 01621 ~shared_release(); 01622 01626 void release(void); 01627 01632 SharedObject *get(void); 01633 01639 shared_release &operator=(SharedPointer &pointer); 01640 }; 01641 01649 template<class T> 01650 class shared_pointer : public SharedPointer 01651 { 01652 public: 01656 inline shared_pointer() : SharedPointer() {} 01657 01665 inline const T *dup(void) 01666 {return static_cast<const T*>(SharedPointer::share());} 01667 01674 inline void replace(T *object) 01675 {SharedPointer::replace(object);} 01676 01681 inline void operator=(T *object) 01682 {replace(object);} 01683 01688 inline T *operator*() 01689 {return dup();} 01690 }; 01691 01699 template<class T> 01700 class locked_pointer : public LockedPointer 01701 { 01702 public: 01706 inline locked_pointer() : LockedPointer() {} 01707 01713 inline T* dup(void) 01714 {return static_cast<T *>(LockedPointer::dup());} 01715 01720 inline void replace(T *object) 01721 {LockedPointer::replace(object);} 01722 01727 inline void operator=(T *object) 01728 {replace(object);} 01729 01735 inline T *operator*() 01736 {return dup();} 01737 }; 01738 01744 template<class T> 01745 class locked_instance : public locked_release 01746 { 01747 public: 01751 inline locked_instance() : locked_release() {} 01752 01757 inline locked_instance(locked_pointer<T> &pointer) : locked_release(pointer) {} 01758 01763 inline T& operator*() const 01764 {return *(static_cast<T&>(object));} 01765 01770 inline T* operator->() const 01771 {return static_cast<T*>(object);} 01772 01777 inline T* get(void) const 01778 {return static_cast<T*>(object);} 01779 }; 01780 01786 template<class T> 01787 class shared_instance : public shared_release 01788 { 01789 public: 01793 inline shared_instance() : shared_release() {} 01794 01800 inline shared_instance(shared_pointer<T> &pointer) : shared_release(pointer) {} 01801 01805 inline const T& operator*() const 01806 {return *(static_cast<const T&>(ptr->pointer));} 01807 01812 inline const T* operator->() const 01813 {return static_cast<const T*>(ptr->pointer);} 01814 01819 inline const T* get(void) const 01820 {return static_cast<const T*>(ptr->pointer);} 01821 }; 01822 01829 template <class T> 01830 class mutex_pointer : public auto_protect 01831 { 01832 public: 01836 inline mutex_pointer() : auto_protect() {} 01837 01842 inline mutex_pointer(T* object) : auto_protect(object) {} 01843 01848 inline T& operator*() const 01849 {return *(static_cast<T&>(auto_protect::object));} 01850 01855 inline T* operator->() const 01856 {return static_cast<T*>(auto_protect::object);} 01857 01862 inline T* get(void) const 01863 {return static_cast<T*>(auto_protect::object);} 01864 }; 01865 01871 inline void start(JoinableThread *thread, int priority = 0) 01872 {thread->start(priority);} 01873 01879 inline void start(DetachedThread *thread, int priority = 0) 01880 {thread->start(priority);} 01881 01885 typedef ConditionalLock condlock_t; 01886 01890 typedef ConditionalAccess accesslock_t; 01891 01895 typedef TimedEvent timedevent_t; 01896 01900 typedef Mutex mutex_t; 01901 01905 typedef ThreadLock rwlock_t; 01906 01910 typedef RecursiveMutex rexlock_t; 01911 01915 typedef Semaphore semaphore_t; 01916 01920 typedef barrier barrier_t; 01921 01926 inline void wait(barrier_t &barrier) 01927 {barrier.wait();} 01928 01934 inline void wait(semaphore_t &semaphore, timeout_t timeout = Timer::inf) 01935 {semaphore.wait(timeout);} 01936 01941 inline void release(semaphore_t &semaphore) 01942 {semaphore.release();} 01943 01948 inline void acquire(mutex_t &mutex) 01949 {mutex.lock();} 01950 01955 inline void release(mutex_t &mutex) 01956 {mutex.release();} 01957 01962 inline void modify(accesslock_t &lock) 01963 {lock.modify();} 01964 01969 inline void access(accesslock_t &lock) 01970 {lock.access();} 01971 01976 inline void release(accesslock_t &lock) 01977 {lock.release();} 01978 01984 inline void commit(accesslock_t &lock) 01985 {lock.commit();} 01986 01991 inline void exclusive(condlock_t &lock) 01992 {lock.exclusive();} 01993 01998 inline void share(condlock_t &lock) 01999 {lock.share();} 02000 02005 inline void modify(condlock_t &lock) 02006 {lock.modify();} 02007 02013 inline void commit(condlock_t &lock) 02014 {lock.commit();} 02015 02020 inline void access(condlock_t &lock) 02021 {lock.access();} 02022 02027 inline void release(condlock_t &lock) 02028 {lock.release();} 02029 02035 inline bool exclusive(rwlock_t &lock, timeout_t timeout = Timer::inf) 02036 {return lock.modify(timeout);} 02037 02043 inline bool share(rwlock_t &lock, timeout_t timeout = Timer::inf) 02044 {return lock.access(timeout);} 02045 02050 inline void release(rwlock_t &lock) 02051 {lock.release();} 02052 02057 inline void lock(rexlock_t &lock) 02058 {lock.lock();} 02059 02064 inline void release(rexlock_t &lock) 02065 {lock.release();} 02066 02067 #define __AUTOLOCK__ autolock __autolock__(this); 02068 02069 #define __SYNC__ for(bool _sync_flag_ = Mutex::protect(this); _sync_flag_; _sync_flag_ = !Mutex::release(this)) 02070 02071 #define __SHARED__ for(bool _sync_flag_ = ThreadLock::reader(this); _sync_flag_; _sync_flag_ = !ThreadLock::release(this)) 02072 02073 #define ___EXCLUSIVE__ for(bool _sync_flag_ = ThreadLock::writer(this); _sync_flag_; _sync_flag_ = !ThreadLock::release(this)) 02074 02075 } // namespace ucommon 02076 02077 #endif