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 00958 unsigned operator++(void); 00959 00963 void wait(void); 00964 00971 bool wait(timeout_t timeout); 00972 00977 inline static void wait(barrier& sync) 00978 {sync.wait();}; 00979 00986 inline static bool wait(barrier& sync, timeout_t timeout) 00987 {return sync.wait(timeout);}; 00988 00989 00995 inline static void set(barrier& sync, unsigned count) 00996 {sync.set(count);}; 00997 }; 00998 01007 class __EXPORT semaphore : public Shared, private Conditional 01008 { 01009 private: 01010 unsigned count, waits, used; 01011 01012 __LOCAL void Shlock(void); 01013 __LOCAL void Unlock(void); 01014 01015 public: 01019 semaphore(unsigned count = 0); 01020 01025 void wait(void); 01026 01034 bool wait(timeout_t timeout); 01035 01040 unsigned getCount(void); 01041 01046 unsigned getUsed(void); 01047 01052 void set(unsigned count); 01053 01057 void release(void); 01058 01062 inline void operator++(void) 01063 {wait();}; 01064 01068 inline void operator--(void) 01069 {release();}; 01070 01075 inline static void wait(semaphore& sync) 01076 {sync.wait();}; 01077 01084 inline static bool wait(semaphore& sync, timeout_t timeout) 01085 {return sync.wait(timeout);}; 01086 01091 inline static void release(semaphore& sync) 01092 {sync.release();}; 01093 }; 01094 01108 class __EXPORT mutex : public Exclusive 01109 { 01110 private: 01111 pthread_mutex_t mlock; 01112 01113 __LOCAL void Exlock(void); 01114 __LOCAL void Unlock(void); 01115 01116 public: 01124 class __EXPORT gaurd 01125 { 01126 private: 01127 void *object; 01128 01129 public: 01134 gaurd(); 01135 01140 gaurd(void *object); 01141 01145 ~gaurd(); 01146 01152 void set(void *object); 01153 01157 void release(void); 01158 01164 inline void operator=(void *pointer) 01165 {set(pointer);}; 01166 }; 01167 01168 01172 mutex(); 01173 01177 ~mutex(); 01178 01182 inline void acquire(void) 01183 {pthread_mutex_lock(&mlock);}; 01184 01188 inline void lock(void) 01189 {pthread_mutex_lock(&mlock);}; 01190 01194 inline void unlock(void) 01195 {pthread_mutex_unlock(&mlock);}; 01196 01200 inline void release(void) 01201 {pthread_mutex_unlock(&mlock);}; 01202 01207 inline static void acquire(mutex& lock) 01208 {pthread_mutex_lock(&lock.mlock);}; 01209 01214 inline static void lock(mutex& lock) 01215 {pthread_mutex_lock(&lock.mlock);}; 01216 01221 inline static void unlock(mutex& lock) 01222 {pthread_mutex_unlock(&lock.mlock);}; 01223 01228 inline static void release(mutex& lock) 01229 {pthread_mutex_unlock(&lock.mlock);}; 01230 01235 inline static void acquire(pthread_mutex_t *lock) 01236 {pthread_mutex_lock(lock);}; 01237 01242 inline static void lock(pthread_mutex_t *lock) 01243 {pthread_mutex_lock(lock);}; 01244 01249 inline static void unlock(pthread_mutex_t *lock) 01250 {pthread_mutex_unlock(lock);}; 01251 01256 inline static void release(pthread_mutex_t *lock) 01257 {pthread_mutex_unlock(lock);}; 01258 01265 static void indexing(unsigned size); 01266 01272 static void protect(void *pointer); 01273 01278 static void release(void *pointer); 01279 }; 01280 01289 class __EXPORT auto_protect 01290 { 01291 private: 01292 // cannot copy... 01293 inline auto_protect(const auto_object &pointer) {}; 01294 01295 protected: 01296 void *object; 01297 01298 auto_protect(); 01299 01300 public: 01305 auto_protect(void *object); 01306 01311 ~auto_protect(); 01312 01316 void release(void); 01317 01322 inline bool operator!() const 01323 {return object == NULL;}; 01324 01329 inline operator bool() const 01330 {return object != NULL;}; 01331 01338 void operator=(void *object); 01339 }; 01340 01352 class __EXPORT LockedPointer 01353 { 01354 private: 01355 friend class locked_release; 01356 pthread_mutex_t mutex; 01357 Object *pointer; 01358 01359 protected: 01363 LockedPointer(); 01364 01369 void replace(Object *object); 01370 01375 Object *dup(void); 01376 01381 inline void operator=(Object *object) 01382 {replace(object);}; 01383 }; 01384 01393 class __EXPORT SharedObject 01394 { 01395 protected: 01396 friend class SharedPointer; 01397 01406 virtual void commit(SharedPointer *pointer); 01407 01408 public: 01412 virtual ~SharedObject(); 01413 }; 01414 01425 class __EXPORT SharedPointer : protected ConditionalAccess 01426 { 01427 private: 01428 friend class shared_release; 01429 SharedObject *pointer; 01430 01431 protected: 01435 SharedPointer(); 01436 01440 ~SharedPointer(); 01441 01448 void replace(SharedObject *object); 01449 01456 SharedObject *share(void); 01457 }; 01458 01469 class __EXPORT Thread 01470 { 01471 protected: 01472 pthread_t tid; 01473 size_t stack; 01474 int priority; 01475 01481 Thread(size_t stack = 0); 01482 01487 void map(void); 01488 01489 public: 01496 void setPriority(void); 01497 01502 static void yield(void); 01503 01508 static void sleep(timeout_t timeout); 01509 01516 static Thread *get(void); 01517 01521 virtual void run(void) = 0; 01522 01526 virtual ~Thread(); 01527 01536 virtual void exit(void); 01537 01541 static void init(void); 01542 01548 static void policy(int polid); 01549 01554 static void concurrency(int level); 01555 01562 static bool equal(pthread_t thread1, pthread_t thread2); 01563 01568 static pthread_t self(void); 01569 }; 01570 01581 class __EXPORT JoinableThread : protected Thread 01582 { 01583 protected: 01584 #ifdef _MSWINDOWS_ 01585 HANDLE joining; 01586 #else 01587 volatile bool running; 01588 #endif 01589 01594 JoinableThread(size_t size = 0); 01595 01600 virtual ~JoinableThread(); 01601 01607 void join(void); 01608 01609 public: 01610 #ifdef _MSWINDOWS_ 01611 inline bool isRunning(void) 01612 {return (joining != INVALID_HANDLE_VALUE);}; 01613 #else 01614 01618 inline bool isRunning(void) 01619 {return running;}; 01620 #endif 01621 01630 void start(int priority = 0); 01631 01636 inline void background(void) 01637 {start(-1);}; 01638 }; 01639 01647 class __EXPORT DetachedThread : protected Thread 01648 { 01649 protected: 01654 DetachedThread(size_t size = 0); 01655 01661 ~DetachedThread(); 01662 01671 void exit(void); 01672 01673 public: 01680 void start(int priority = 0); 01681 }; 01682 01691 class __EXPORT locked_release 01692 { 01693 protected: 01694 Object *object; 01699 locked_release(); 01700 01706 locked_release(const locked_release &object); 01707 01708 public: 01714 locked_release(LockedPointer &pointer); 01715 01720 ~locked_release(); 01721 01725 void release(void); 01726 01732 locked_release &operator=(LockedPointer &pointer); 01733 }; 01734 01744 class __EXPORT shared_release 01745 { 01746 protected: 01747 SharedPointer *ptr; 01752 shared_release(); 01753 01759 shared_release(const shared_release &object); 01760 01761 public: 01766 shared_release(SharedPointer &pointer); 01767 01773 ~shared_release(); 01774 01778 void release(void); 01779 01784 SharedObject *get(void); 01785 01791 shared_release &operator=(SharedPointer &pointer); 01792 }; 01793 01801 template<class T> 01802 class shared_pointer : public SharedPointer 01803 { 01804 public: 01808 inline shared_pointer() : SharedPointer() {}; 01809 01817 inline const T *dup(void) 01818 {return static_cast<const T*>(SharedPointer::share());}; 01819 01826 inline void replace(T *object) 01827 {SharedPointer::replace(object);}; 01828 01833 inline void operator=(T *object) 01834 {replace(object);}; 01835 01840 inline T *operator*() 01841 {return dup();}; 01842 }; 01843 01851 template<class T> 01852 class locked_pointer : public LockedPointer 01853 { 01854 public: 01858 inline locked_pointer() : LockedPointer() {}; 01859 01865 inline T* dup(void) 01866 {return static_cast<T *>(LockedPointer::dup());}; 01867 01872 inline void replace(T *object) 01873 {LockedPointer::replace(object);}; 01874 01879 inline void operator=(T *object) 01880 {replace(object);}; 01881 01887 inline T *operator*() 01888 {return dup();}; 01889 }; 01890 01896 template<class T> 01897 class locked_instance : public locked_release 01898 { 01899 public: 01903 inline locked_instance() : locked_release() {}; 01904 01909 inline locked_instance(locked_pointer<T> &pointer) : locked_release(pointer) {}; 01910 01915 inline T& operator*() const 01916 {return *(static_cast<T *>(object));}; 01917 01922 inline T* operator->() const 01923 {return static_cast<T*>(object);}; 01924 01929 inline T* get(void) const 01930 {return static_cast<T*>(object);}; 01931 }; 01932 01938 template<class T> 01939 class shared_instance : public shared_release 01940 { 01941 public: 01945 inline shared_instance() : shared_release() {}; 01946 01952 inline shared_instance(shared_pointer<T> &pointer) : shared_release(pointer) {}; 01953 01957 inline const T& operator*() const 01958 {return *(static_cast<const T *>(ptr->pointer));}; 01959 01964 inline const T* operator->() const 01965 {return static_cast<const T*>(ptr->pointer);}; 01966 01971 inline const T* get(void) const 01972 {return static_cast<const T*>(ptr->pointer);}; 01973 }; 01974 01981 template <class T> 01982 class mutex_pointer : public auto_protect 01983 { 01984 public: 01988 inline mutex_pointer() : auto_protect() {}; 01989 01994 inline mutex_pointer(T* object) : auto_protect(object) {}; 01995 02000 inline T& operator*() const 02001 {return *(static_cast<T*>(auto_protect::object));}; 02002 02007 inline T* operator->() const 02008 {return static_cast<T*>(auto_protect::object);}; 02009 02014 inline T* get(void) const 02015 {return static_cast<T*>(auto_protect::object);}; 02016 }; 02017 02023 inline void start(JoinableThread *thread, int priority = 0) 02024 {thread->start(priority);} 02025 02031 inline void start(DetachedThread *thread, int priority = 0) 02032 {thread->start(priority);} 02033 02037 typedef ConditionalLock condlock_t; 02038 02042 typedef ConditionalAccess accesslock_t; 02043 02047 typedef TimedEvent timedevent_t; 02048 02052 typedef mutex mutex_t; 02053 02058 typedef mutex Mutex; 02059 02063 typedef rwlock rwlock_t; 02064 02068 typedef rexlock rexlock_t; 02069 02073 typedef semaphore semaphore_t; 02074 02078 typedef barrier barrier_t; 02079 02084 inline void wait(barrier_t &barrier) 02085 {barrier.wait();} 02086 02092 inline void wait(semaphore_t &semaphore, timeout_t timeout = Timer::inf) 02093 {semaphore.wait(timeout);} 02094 02099 inline void release(semaphore_t &semaphore) 02100 {semaphore.release();} 02101 02106 inline void acquire(mutex_t &mutex) 02107 {mutex.lock();} 02108 02113 inline void release(mutex_t &mutex) 02114 {mutex.release();} 02115 02120 inline void modify(accesslock_t &lock) 02121 {lock.modify();} 02122 02127 inline void access(accesslock_t &lock) 02128 {lock.access();} 02129 02134 inline void release(accesslock_t &lock) 02135 {lock.release();} 02136 02142 inline void commit(accesslock_t &lock) 02143 {lock.commit();} 02144 02149 inline void exclusive(condlock_t &lock) 02150 {lock.exclusive();} 02151 02156 inline void share(condlock_t &lock) 02157 {lock.share();} 02158 02163 inline void modify(condlock_t &lock) 02164 {lock.modify();} 02165 02171 inline void commit(condlock_t &lock) 02172 {lock.commit();} 02173 02178 inline void access(condlock_t &lock) 02179 {lock.access();} 02180 02185 inline void release(condlock_t &lock) 02186 {lock.release();} 02187 02193 inline bool exclusive(rwlock_t &lock, timeout_t timeout = Timer::inf) 02194 {return lock.modify(timeout);} 02195 02201 inline bool share(rwlock_t &lock, timeout_t timeout = Timer::inf) 02202 {return lock.access(timeout);} 02203 02208 inline void release(rwlock_t &lock) 02209 {lock.release();} 02210 02215 inline void lock(rexlock_t &lock) 02216 {lock.lock();} 02217 02222 inline void release(rexlock_t &lock) 02223 {lock.release();} 02224 02225 END_NAMESPACE 02226 02227 #define ENTER_EXCLUSIVE \ 02228 do { static pthread_mutex_t __sync__ = PTHREAD_MUTEX_INITIALIZER; \ 02229 pthread_mutex_lock(&__sync__); 02230 02231 #define LEAVE_EXCLUSIVE \ 02232 pthread_mutex_unlock(&__sync__);} while(0); 02233 02234 #endif