ucommon
|
00001 // Copyright (C) 2006-2014 David Sugar, Tycho Softworks. 00002 // 00003 // This file is part of GNU uCommon C++. 00004 // 00005 // GNU uCommon C++ is free software: you can redistribute it and/or modify 00006 // it under the terms of the GNU Lesser General Public License as published 00007 // by the Free Software Foundation, either version 3 of the License, or 00008 // (at your option) any later version. 00009 // 00010 // GNU uCommon C++ is distributed in the hope that it will be useful, 00011 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00013 // GNU Lesser General Public License for more details. 00014 // 00015 // You should have received a copy of the GNU Lesser General Public License 00016 // along with GNU uCommon C++. If not, see <http://www.gnu.org/licenses/>. 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(_MSTHREADS_) 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 _MSTHREADS_ 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(_MSTHREADS_) && !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(_MSTHREADS_) 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 _MSTHREADS_ 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 _MSTHREADS_ 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 // cannot copy... 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 // may be used in future if we need cancelable threads... 01250 #ifdef _MSTHREADS_ 01251 HANDLE cancellor; 01252 #else 01253 void *cancellor; 01254 #endif 01255 01256 enum {R_UNUSED} reserved; // cancel mode? 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 _MSTHREADS_ 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 } // namespace ucommon 02062 02063 #endif