ucommon
|
00001 // Copyright (C) 2006-2010 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_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 #ifdef _MSWINDOWS_ 00092 enum {SIGNAL = 0, BROADCAST = 1}; 00093 HANDLE events[2]; 00094 unsigned waiting; 00095 CRITICAL_SECTION mlock; 00096 CRITICAL_SECTION mutex; 00097 #else 00098 #ifndef __PTH__ 00099 class __LOCAL attribute 00100 { 00101 public: 00102 pthread_condattr_t attr; 00103 attribute(); 00104 }; 00105 00106 __LOCAL static attribute attr; 00107 #endif 00108 00109 pthread_cond_t cond; 00110 pthread_mutex_t mutex; 00111 #endif 00112 00113 protected: 00114 friend class TimedEvent; 00115 00121 bool wait(timeout_t timeout); 00122 00128 bool wait(struct timespec *timeout); 00129 00130 #ifdef _MSWINDOWS_ 00131 inline void lock(void) 00132 {EnterCriticalSection(&mutex);}; 00133 00134 inline void unlock(void) 00135 {LeaveCriticalSection(&mutex);}; 00136 00137 void wait(void); 00138 void signal(void); 00139 void broadcast(void); 00140 00141 #else 00142 00145 inline void lock(void) 00146 {pthread_mutex_lock(&mutex);}; 00147 00151 inline void unlock(void) 00152 {pthread_mutex_unlock(&mutex);}; 00153 00157 inline void wait(void) 00158 {pthread_cond_wait(&cond, &mutex);}; 00159 00163 inline void signal(void) 00164 {pthread_cond_signal(&cond);}; 00165 00169 inline void broadcast(void) 00170 {pthread_cond_broadcast(&cond);}; 00171 #endif 00172 00176 Conditional(); 00177 00181 ~Conditional(); 00182 00183 public: 00184 #if !defined(_MSWINDOWS_) && !defined(__PTH__) 00185 00190 static inline pthread_condattr_t *initializer(void) 00191 {return &attr.attr;}; 00192 #endif 00193 00200 static void gettimeout(timeout_t timeout, struct timespec *hires); 00201 }; 00202 00210 class __EXPORT ConditionalAccess : private Conditional 00211 { 00212 private: 00213 #ifndef _MSWINDOWS_ 00214 pthread_cond_t bcast; 00215 #endif 00216 00217 protected: 00218 unsigned pending, waiting, sharing; 00219 00225 bool waitSignal(timeout_t timeout); 00226 00232 bool waitBroadcast(timeout_t timeout); 00233 00234 00240 bool waitSignal(struct timespec *timeout); 00241 00247 bool waitBroadcast(struct timespec *timeout); 00248 00255 inline static void gettimeout(timeout_t timeout, struct timespec *hires) 00256 {Conditional::gettimeout(timeout, hires);}; 00257 00258 00259 #ifdef _MSWINDOWS_ 00260 inline void lock(void) 00261 {EnterCriticalSection(&mutex);}; 00262 00263 inline void unlock(void) 00264 {LeaveCriticalSection(&mutex);}; 00265 00266 void waitSignal(void); 00267 void waitBroadcast(void); 00268 00269 inline void signal(void) 00270 {Conditional::signal();}; 00271 00272 inline void broadcast(void) 00273 {Conditional::broadcast();}; 00274 00275 #else 00276 00279 inline void lock(void) 00280 {pthread_mutex_lock(&mutex);}; 00281 00285 inline void unlock(void) 00286 {pthread_mutex_unlock(&mutex);}; 00287 00291 inline void waitSignal(void) 00292 {pthread_cond_wait(&cond, &mutex);}; 00293 00297 inline void waitBroadcast(void) 00298 {pthread_cond_wait(&bcast, &mutex);}; 00299 00300 00304 inline void signal(void) 00305 {pthread_cond_signal(&cond);}; 00306 00310 inline void broadcast(void) 00311 {pthread_cond_broadcast(&bcast);}; 00312 #endif 00313 public: 00317 ConditionalAccess(); 00318 00322 ~ConditionalAccess(); 00323 00327 void access(void); 00328 00332 void modify(void); 00333 00337 void release(void); 00338 00342 void commit(void); 00343 00350 void limit_sharing(unsigned max); 00351 }; 00352 00361 class __EXPORT TimedEvent : public Timer 00362 { 00363 private: 00364 #ifdef _MSWINDOWS_ 00365 HANDLE event; 00366 #else 00367 pthread_cond_t cond; 00368 bool signalled; 00369 #endif 00370 pthread_mutex_t mutex; 00371 00372 protected: 00377 void lock(void); 00378 00383 void release(void); 00384 00392 bool sync(void); 00393 00394 public: 00398 TimedEvent(void); 00399 00404 TimedEvent(timeout_t timeout); 00405 00410 TimedEvent(time_t timeout); 00411 00415 ~TimedEvent(); 00416 00422 void signal(void); 00423 00430 bool wait(timeout_t timeout); 00431 00435 void reset(void); 00436 00441 inline static void signal(TimedEvent& timed) 00442 {timed.signal();}; 00443 00448 inline static void reset(TimedEvent& timed) 00449 {timed.reset();}; 00450 00457 inline static bool wait(TimedEvent& timed, timeout_t timeout) 00458 {return timed.wait(timeout);}; 00459 }; 00460 00468 class __EXPORT rexlock : private Conditional, public Exclusive 00469 { 00470 private: 00471 unsigned waiting; 00472 unsigned lockers; 00473 pthread_t locker; 00474 00475 __LOCAL void Exlock(void); 00476 __LOCAL void Unlock(void); 00477 00478 public: 00482 rexlock(); 00483 00487 void lock(void); 00488 00492 bool lock(timeout_t timeout); 00493 00497 void release(void); 00498 00503 unsigned getLocking(void); 00504 00509 unsigned getWaiting(void); 00510 00515 inline static void lock(rexlock& rex) 00516 {rex.lock();}; 00517 00522 inline static void release(rexlock& rex) 00523 {rex.release();}; 00524 }; 00525 00538 class __EXPORT rwlock : private ConditionalAccess, public Exclusive, public Shared 00539 { 00540 private: 00541 unsigned writers; 00542 pthread_t writeid; 00543 00544 __LOCAL void Exlock(void); 00545 __LOCAL void Shlock(void); 00546 __LOCAL void Unlock(void); 00547 00548 public: 00556 class __EXPORT gaurd_reader 00557 { 00558 private: 00559 void *object; 00560 00561 public: 00566 gaurd_reader(); 00567 00572 gaurd_reader(void *object); 00573 00577 ~gaurd_reader(); 00578 00584 void set(void *object); 00585 00589 void release(void); 00590 00596 inline void operator=(void *pointer) 00597 {set(pointer);}; 00598 }; 00599 00607 class __EXPORT gaurd_writer 00608 { 00609 private: 00610 void *object; 00611 00612 public: 00617 gaurd_writer(); 00618 00623 gaurd_writer(void *object); 00624 00628 ~gaurd_writer(); 00629 00635 void set(void *object); 00636 00640 void release(void); 00641 00647 inline void operator=(void *pointer) 00648 {set(pointer);}; 00649 }; 00650 00654 rwlock(); 00655 00661 bool modify(timeout_t timeout = Timer::inf); 00662 00668 bool access(timeout_t timeout = Timer::inf); 00669 00676 static void indexing(unsigned size); 00677 00685 static bool writer(void *object, timeout_t timeout = Timer::inf); 00686 00694 static bool reader(void *object, timeout_t timeout = Timer::inf); 00695 00700 static void release(void *object); 00701 00705 void release(void); 00706 00711 unsigned getAccess(void); 00712 00717 unsigned getModify(void); 00718 00723 unsigned getWaiting(void); 00724 00731 inline static bool modify(rwlock& lock, timeout_t timeout = Timer::inf) 00732 {return lock.modify(timeout);}; 00733 00740 inline static bool access(rwlock& lock, timeout_t timeout = Timer::inf) 00741 {return lock.access(timeout);}; 00742 00747 inline static void release(rwlock& lock) 00748 {lock.release();}; 00749 }; 00750 00761 class __EXPORT ReusableAllocator : protected Conditional 00762 { 00763 protected: 00764 ReusableObject *freelist; 00765 unsigned waiting; 00766 00770 ReusableAllocator(); 00771 00777 inline ReusableObject *next(ReusableObject *object) 00778 {return object->getNext();}; 00779 00784 void release(ReusableObject *object); 00785 }; 00786 00797 class __EXPORT ConditionalLock : protected ConditionalAccess, public Shared 00798 { 00799 private: 00800 class Context : public LinkedObject 00801 { 00802 public: 00803 inline Context(LinkedObject **root) : LinkedObject(root) {}; 00804 00805 pthread_t thread; 00806 unsigned count; 00807 }; 00808 00809 LinkedObject *contexts; 00810 00811 __LOCAL void Shlock(void); 00812 __LOCAL void Unlock(void); 00813 __LOCAL void Exclusive(void); 00814 __LOCAL void Share(void); 00815 __LOCAL Context *getContext(void); 00816 00817 public: 00821 ConditionalLock(); 00822 00826 ~ConditionalLock(); 00827 00831 void modify(void); 00832 00836 void commit(void); 00837 00841 void access(void); 00842 00846 void release(void); 00847 00852 void exclusive(void); 00853 00857 void share(void); 00858 00862 unsigned getReaders(void); 00863 00867 unsigned getWaiters(void); 00868 00873 inline static void modify(ConditionalLock& lock) 00874 {lock.modify();}; 00875 00880 inline static void commit(ConditionalLock& lock) 00881 {lock.commit();}; 00882 00887 inline static void release(ConditionalLock& lock) 00888 {lock.release();}; 00889 00894 inline static void access(ConditionalLock& lock) 00895 {lock.access();}; 00896 00901 inline static void exclusive(ConditionalLock& lock) 00902 {lock.exclusive();}; 00903 00908 inline static void share(ConditionalLock& lock) 00909 {lock.share();}; 00910 }; 00911 00924 class __EXPORT barrier : private Conditional 00925 { 00926 private: 00927 unsigned count; 00928 unsigned waits; 00929 00930 public: 00935 barrier(unsigned count); 00936 00940 ~barrier(); 00941 00947 void set(unsigned count); 00948 00952 void inc(void); 00953 00957 void dec(void); 00958 00963 unsigned operator++(void); 00964 00965 unsigned operator--(void); 00966 00970 void wait(void); 00971 00978 bool wait(timeout_t timeout); 00979 00984 inline static void wait(barrier& sync) 00985 {sync.wait();}; 00986 00993 inline static bool wait(barrier& sync, timeout_t timeout) 00994 {return sync.wait(timeout);}; 00995 00996 01002 inline static void set(barrier& sync, unsigned count) 01003 {sync.set(count);}; 01004 }; 01005 01014 class __EXPORT semaphore : public Shared, private Conditional 01015 { 01016 private: 01017 unsigned count, waits, used; 01018 01019 __LOCAL void Shlock(void); 01020 __LOCAL void Unlock(void); 01021 01022 public: 01026 semaphore(unsigned count = 0); 01027 01032 void wait(void); 01033 01041 bool wait(timeout_t timeout); 01042 01047 unsigned getCount(void); 01048 01053 unsigned getUsed(void); 01054 01059 void set(unsigned count); 01060 01064 void release(void); 01065 01069 inline void operator++(void) 01070 {wait();}; 01071 01075 inline void operator--(void) 01076 {release();}; 01077 01082 inline static void wait(semaphore& sync) 01083 {sync.wait();}; 01084 01091 inline static bool wait(semaphore& sync, timeout_t timeout) 01092 {return sync.wait(timeout);}; 01093 01098 inline static void release(semaphore& sync) 01099 {sync.release();}; 01100 }; 01101 01115 class __EXPORT mutex : public Exclusive 01116 { 01117 private: 01118 pthread_mutex_t mlock; 01119 01120 __LOCAL void Exlock(void); 01121 __LOCAL void Unlock(void); 01122 01123 public: 01131 class __EXPORT gaurd 01132 { 01133 private: 01134 void *object; 01135 01136 public: 01141 gaurd(); 01142 01147 gaurd(void *object); 01148 01152 ~gaurd(); 01153 01159 void set(void *object); 01160 01164 void release(void); 01165 01171 inline void operator=(void *pointer) 01172 {set(pointer);}; 01173 }; 01174 01175 01179 mutex(); 01180 01184 ~mutex(); 01185 01189 inline void acquire(void) 01190 {pthread_mutex_lock(&mlock);}; 01191 01195 inline void lock(void) 01196 {pthread_mutex_lock(&mlock);}; 01197 01201 inline void unlock(void) 01202 {pthread_mutex_unlock(&mlock);}; 01203 01207 inline void release(void) 01208 {pthread_mutex_unlock(&mlock);}; 01209 01214 inline static void acquire(mutex& lock) 01215 {pthread_mutex_lock(&lock.mlock);}; 01216 01221 inline static void lock(mutex& lock) 01222 {pthread_mutex_lock(&lock.mlock);}; 01223 01228 inline static void unlock(mutex& lock) 01229 {pthread_mutex_unlock(&lock.mlock);}; 01230 01235 inline static void release(mutex& lock) 01236 {pthread_mutex_unlock(&lock.mlock);}; 01237 01242 inline static void acquire(pthread_mutex_t *lock) 01243 {pthread_mutex_lock(lock);}; 01244 01249 inline static void lock(pthread_mutex_t *lock) 01250 {pthread_mutex_lock(lock);}; 01251 01256 inline static void unlock(pthread_mutex_t *lock) 01257 {pthread_mutex_unlock(lock);}; 01258 01263 inline static void release(pthread_mutex_t *lock) 01264 {pthread_mutex_unlock(lock);}; 01265 01272 static void indexing(unsigned size); 01273 01279 static void protect(void *pointer); 01280 01285 static void release(void *pointer); 01286 }; 01287 01296 class __EXPORT auto_protect 01297 { 01298 private: 01299 // cannot copy... 01300 inline auto_protect(const auto_object &pointer) {}; 01301 01302 protected: 01303 void *object; 01304 01305 auto_protect(); 01306 01307 public: 01312 auto_protect(void *object); 01313 01318 ~auto_protect(); 01319 01323 void release(void); 01324 01329 inline bool operator!() const 01330 {return object == NULL;}; 01331 01336 inline operator bool() const 01337 {return object != NULL;}; 01338 01345 void operator=(void *object); 01346 }; 01347 01359 class __EXPORT LockedPointer 01360 { 01361 private: 01362 friend class locked_release; 01363 pthread_mutex_t mutex; 01364 Object *pointer; 01365 01366 protected: 01370 LockedPointer(); 01371 01376 void replace(Object *object); 01377 01382 Object *dup(void); 01383 01388 inline void operator=(Object *object) 01389 {replace(object);}; 01390 }; 01391 01400 class __EXPORT SharedObject 01401 { 01402 protected: 01403 friend class SharedPointer; 01404 01413 virtual void commit(SharedPointer *pointer); 01414 01415 public: 01419 virtual ~SharedObject(); 01420 }; 01421 01432 class __EXPORT SharedPointer : protected ConditionalAccess 01433 { 01434 private: 01435 friend class shared_release; 01436 SharedObject *pointer; 01437 01438 protected: 01442 SharedPointer(); 01443 01447 ~SharedPointer(); 01448 01455 void replace(SharedObject *object); 01456 01463 SharedObject *share(void); 01464 }; 01465 01476 class __EXPORT Thread 01477 { 01478 protected: 01479 pthread_t tid; 01480 size_t stack; 01481 int priority; 01482 01488 Thread(size_t stack = 0); 01489 01494 void map(void); 01495 01496 public: 01503 void setPriority(void); 01504 01509 static void yield(void); 01510 01515 static void sleep(timeout_t timeout); 01516 01523 static Thread *get(void); 01524 01528 virtual void run(void) = 0; 01529 01533 virtual ~Thread(); 01534 01543 virtual void exit(void); 01544 01548 static void init(void); 01549 01555 static void policy(int polid); 01556 01561 static void concurrency(int level); 01562 01569 static bool equal(pthread_t thread1, pthread_t thread2); 01570 01575 static pthread_t self(void); 01576 }; 01577 01588 class __EXPORT JoinableThread : protected Thread 01589 { 01590 protected: 01591 #ifdef _MSWINDOWS_ 01592 HANDLE joining; 01593 #else 01594 volatile bool running; 01595 #endif 01596 01601 JoinableThread(size_t size = 0); 01602 01607 virtual ~JoinableThread(); 01608 01614 void join(void); 01615 01616 public: 01617 #ifdef _MSWINDOWS_ 01618 inline bool isRunning(void) 01619 {return (joining != INVALID_HANDLE_VALUE);}; 01620 #else 01621 01625 inline bool isRunning(void) 01626 {return running;}; 01627 #endif 01628 01637 void start(int priority = 0); 01638 01643 inline void background(void) 01644 {start(-1);}; 01645 }; 01646 01654 class __EXPORT DetachedThread : protected Thread 01655 { 01656 protected: 01661 DetachedThread(size_t size = 0); 01662 01668 ~DetachedThread(); 01669 01678 void exit(void); 01679 01680 public: 01687 void start(int priority = 0); 01688 }; 01689 01698 class __EXPORT locked_release 01699 { 01700 protected: 01701 Object *object; 01706 locked_release(); 01707 01713 locked_release(const locked_release &object); 01714 01715 public: 01721 locked_release(LockedPointer &pointer); 01722 01727 ~locked_release(); 01728 01732 void release(void); 01733 01739 locked_release &operator=(LockedPointer &pointer); 01740 }; 01741 01751 class __EXPORT shared_release 01752 { 01753 protected: 01754 SharedPointer *ptr; 01759 shared_release(); 01760 01766 shared_release(const shared_release &object); 01767 01768 public: 01773 shared_release(SharedPointer &pointer); 01774 01780 ~shared_release(); 01781 01785 void release(void); 01786 01791 SharedObject *get(void); 01792 01798 shared_release &operator=(SharedPointer &pointer); 01799 }; 01800 01808 template<class T> 01809 class shared_pointer : public SharedPointer 01810 { 01811 public: 01815 inline shared_pointer() : SharedPointer() {}; 01816 01824 inline const T *dup(void) 01825 {return static_cast<const T*>(SharedPointer::share());}; 01826 01833 inline void replace(T *object) 01834 {SharedPointer::replace(object);}; 01835 01840 inline void operator=(T *object) 01841 {replace(object);}; 01842 01847 inline T *operator*() 01848 {return dup();}; 01849 }; 01850 01858 template<class T> 01859 class locked_pointer : public LockedPointer 01860 { 01861 public: 01865 inline locked_pointer() : LockedPointer() {}; 01866 01872 inline T* dup(void) 01873 {return static_cast<T *>(LockedPointer::dup());}; 01874 01879 inline void replace(T *object) 01880 {LockedPointer::replace(object);}; 01881 01886 inline void operator=(T *object) 01887 {replace(object);}; 01888 01894 inline T *operator*() 01895 {return dup();}; 01896 }; 01897 01903 template<class T> 01904 class locked_instance : public locked_release 01905 { 01906 public: 01910 inline locked_instance() : locked_release() {}; 01911 01916 inline locked_instance(locked_pointer<T> &pointer) : locked_release(pointer) {}; 01917 01922 inline T& operator*() const 01923 {return *(static_cast<T *>(object));}; 01924 01929 inline T* operator->() const 01930 {return static_cast<T*>(object);}; 01931 01936 inline T* get(void) const 01937 {return static_cast<T*>(object);}; 01938 }; 01939 01945 template<class T> 01946 class shared_instance : public shared_release 01947 { 01948 public: 01952 inline shared_instance() : shared_release() {}; 01953 01959 inline shared_instance(shared_pointer<T> &pointer) : shared_release(pointer) {}; 01960 01964 inline const T& operator*() const 01965 {return *(static_cast<const T *>(ptr->pointer));}; 01966 01971 inline const T* operator->() const 01972 {return static_cast<const T*>(ptr->pointer);}; 01973 01978 inline const T* get(void) const 01979 {return static_cast<const T*>(ptr->pointer);}; 01980 }; 01981 01988 template <class T> 01989 class mutex_pointer : public auto_protect 01990 { 01991 public: 01995 inline mutex_pointer() : auto_protect() {}; 01996 02001 inline mutex_pointer(T* object) : auto_protect(object) {}; 02002 02007 inline T& operator*() const 02008 {return *(static_cast<T*>(auto_protect::object));}; 02009 02014 inline T* operator->() const 02015 {return static_cast<T*>(auto_protect::object);}; 02016 02021 inline T* get(void) const 02022 {return static_cast<T*>(auto_protect::object);}; 02023 }; 02024 02030 inline void start(JoinableThread *thread, int priority = 0) 02031 {thread->start(priority);} 02032 02038 inline void start(DetachedThread *thread, int priority = 0) 02039 {thread->start(priority);} 02040 02044 typedef ConditionalLock condlock_t; 02045 02049 typedef ConditionalAccess accesslock_t; 02050 02054 typedef TimedEvent timedevent_t; 02055 02059 typedef mutex mutex_t; 02060 02065 typedef mutex Mutex; 02066 02070 typedef rwlock rwlock_t; 02071 02075 typedef rexlock rexlock_t; 02076 02080 typedef semaphore semaphore_t; 02081 02085 typedef barrier barrier_t; 02086 02091 inline void wait(barrier_t &barrier) 02092 {barrier.wait();} 02093 02099 inline void wait(semaphore_t &semaphore, timeout_t timeout = Timer::inf) 02100 {semaphore.wait(timeout);} 02101 02106 inline void release(semaphore_t &semaphore) 02107 {semaphore.release();} 02108 02113 inline void acquire(mutex_t &mutex) 02114 {mutex.lock();} 02115 02120 inline void release(mutex_t &mutex) 02121 {mutex.release();} 02122 02127 inline void modify(accesslock_t &lock) 02128 {lock.modify();} 02129 02134 inline void access(accesslock_t &lock) 02135 {lock.access();} 02136 02141 inline void release(accesslock_t &lock) 02142 {lock.release();} 02143 02149 inline void commit(accesslock_t &lock) 02150 {lock.commit();} 02151 02156 inline void exclusive(condlock_t &lock) 02157 {lock.exclusive();} 02158 02163 inline void share(condlock_t &lock) 02164 {lock.share();} 02165 02170 inline void modify(condlock_t &lock) 02171 {lock.modify();} 02172 02178 inline void commit(condlock_t &lock) 02179 {lock.commit();} 02180 02185 inline void access(condlock_t &lock) 02186 {lock.access();} 02187 02192 inline void release(condlock_t &lock) 02193 {lock.release();} 02194 02200 inline bool exclusive(rwlock_t &lock, timeout_t timeout = Timer::inf) 02201 {return lock.modify(timeout);} 02202 02208 inline bool share(rwlock_t &lock, timeout_t timeout = Timer::inf) 02209 {return lock.access(timeout);} 02210 02215 inline void release(rwlock_t &lock) 02216 {lock.release();} 02217 02222 inline void lock(rexlock_t &lock) 02223 {lock.lock();} 02224 02229 inline void release(rexlock_t &lock) 02230 {lock.release();} 02231 02232 END_NAMESPACE 02233 02234 #define ENTER_EXCLUSIVE \ 02235 do { static pthread_mutex_t __sync__ = PTHREAD_MUTEX_INITIALIZER; \ 02236 pthread_mutex_lock(&__sync__); 02237 02238 #define LEAVE_EXCLUSIVE \ 02239 pthread_mutex_unlock(&__sync__);} while(0); 02240 02241 #endif