00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041 #ifndef __CCXX_THREAD_H__
00042 #define __CCXX_THREAD_H__
00043
00044 #ifndef WIN32
00045 #define __CCXX_POSIX
00046
00047 #ifndef _REENTRANT
00048 #define _REENTRANT
00049 #endif
00050
00051 #ifndef _THREAD_SAFE
00052 #define _THREAD_SAFE
00053 #endif
00054 #else // WIN32
00055 #include <setjmp.h>
00056 #endif // !WIN32
00057
00058 #ifndef __CCXX_CONFIG_H__
00059 #include <cc++/config.h>
00060 #endif
00061
00062 #ifndef __CCXX_EXCEPTION_H__
00063 #include <cc++/exception.h>
00064 #endif
00065
00066 #ifndef WIN32
00067 #if defined(__FreeBSD__) && __FreeBSD__ <= 3
00068 #define _SYSV_SEMAPHORES
00069 #endif
00070
00071 #ifndef HAVE_PTHREAD_H
00072 #include <pthread.h>
00073 #ifndef _SYSV_SEMAPHORES
00074 #include <semaphore.h>
00075 #endif
00076 #endif
00077 #endif // !WIN32
00078
00079 #if _MSC_VER > 1000
00080 #pragma once
00081 #endif
00082
00083 #ifndef WIN32
00084 #include <time.h>
00085 #include <signal.h>
00086 #include <setjmp.h>
00087 #include <unistd.h>
00088
00089 #ifdef __linux__
00090 #define _SIG_THREAD_ALARM
00091 #endif
00092
00093 #ifdef _THR_UNIXWARE
00094 #undef PTHREAD_MUTEXTYPE_RECURSIVE
00095 #endif
00096
00097 typedef pthread_t cctid_t;
00098 typedef unsigned long timeout_t;
00099 #else // WIN32
00100 typedef DWORD cctid_t;
00101 typedef DWORD timeout_t;
00102
00103 #define MAX_SEM_VALUE 1000000
00104 #if defined(__MINGW32__) || defined(__CYGWIN32__)
00105 #include <Windows32/CommonFunctions.h>
00106 #else
00107 __declspec(dllimport) long __stdcall InterlockedIncrement(long *);
00108 __declspec(dllimport) long __stdcall InterlockedDecrement(long *);
00109 __declspec(dllimport) long __stdcall InterlockedExchange(long *, long);
00110 #endif
00111
00112 #endif // !WIN32
00113
00114 #ifdef __NAMESPACES__
00115 namespace ost {
00116 #endif
00117
00118 enum throw_t {
00119 THROW_NOTHING,
00120 THROW_OBJECT,
00121 THROW_EXCEPTION
00122 };
00123 typedef enum throw_t throw_t;
00124 class Thread;
00125
00126 #define TIMEOUT_INF ~((timeout_t) 0)
00127
00128 #define ENTER_CRITICAL EnterMutex();
00129 #define LEAVE_CRITICAL LeaveMutex();
00130 #define ENTER_DEFERRED setCancel(THREAD_CANCEL_DEFERRED);
00131 #define LEAVE_DEFERRED setCancel(THREAD_CANCEL_IMMEDIATE);
00132
00133 enum thread_cancel_t
00134 {
00135 THREAD_CANCEL_INITIAL=0,
00136 THREAD_CANCEL_DEFERRED=1,
00137 THREAD_CANCEL_IMMEDIATE,
00138 THREAD_CANCEL_DISABLED,
00139 THREAD_CANCEL_DEFAULT=THREAD_CANCEL_DEFERRED
00140 };
00141 typedef enum thread_cancel_t thread_cancel_t;
00142
00143 enum thread_suspend_t
00144 {
00145 THREAD_SUSPEND_ENABLE,
00146 THREAD_SUSPEND_DISABLE
00147 };
00148 typedef enum thread_suspend_t thread_suspend_t;
00149
00150 #ifndef WIN32
00151
00152
00153
00154
00155
00156
00157 #undef sleep
00158 #define psleep(x) (sleep)(x)
00159
00160 static RETSIGTYPE ccxx_sigsuspend(int);
00161 extern "C" void execHandler(Thread *th);
00162
00163 #endif // !WIN32
00164
00165
00166 CCXX_EXPORT(Thread*) getThread(void);
00167 CCXX_EXPORT(throw_t) getException(void);
00168 CCXX_EXPORT(void) setException(throw_t mode);
00169 CCXX_EXPORT(void) ccxx_sleep(timeout_t msec);
00170 CCXX_EXPORT(void) ccxx_yield(void);
00171
00172 #undef Yield
00173 #define sleep(x) ccxx_sleep((x) * 1000)
00174 #define yield() ccxx_yield()
00175
00176 #ifdef WIN32
00177 CCXX_EXPORT(DWORD) waitThread(HANDLE hRef, timeout_t timeout);
00178 #endif
00179
00180 class Conditional;
00181 class CCXX_CLASS_EXPORT Event;
00182
00226 class CCXX_CLASS_EXPORT Mutex
00227 {
00228 friend class Conditional;
00229 friend class Event;
00230 private:
00231 #ifndef WIN32
00232 #ifndef PTHREAD_MUTEXTYPE_RECURSIVE
00233 volatile int _level;
00234 volatile Thread *_tid;
00235 #endif
00236
00244 pthread_mutex_t _mutex;
00245 #else
00246 HANDLE mutex;
00247 #endif
00248
00249 public:
00253 Mutex();
00254
00260 virtual ~Mutex();
00261
00269 void EnterMutex(void);
00270
00281 bool TryEnterMutex(void);
00282
00293 void LeaveMutex(void);
00294 };
00295
00317 class MutexLock
00318 {
00319 private:
00320 Mutex& mutex;
00321 public:
00325 MutexLock( Mutex& _mutex ) : mutex( _mutex )
00326 { mutex.EnterMutex(); }
00330
00331 ~MutexLock()
00332 { mutex.LeaveMutex(); }
00333 };
00334
00343 class CCXX_CLASS_EXPORT ThreadLock
00344 {
00345 private:
00346 #ifdef HAVE_PTHREAD_RWLOCK
00347 pthread_rwlock_t _lock;
00348 #else
00349 Mutex mutex;
00350 #endif
00351
00352 public:
00356 ThreadLock();
00357
00361 virtual ~ThreadLock();
00362
00366 void ReadLock(void);
00367
00371 void WriteLock(void);
00372
00378 bool TryReadLock(void);
00379
00385 bool TryWriteLock(void);
00386
00390 void Unlock(void);
00391 };
00392
00402 class CCXX_CLASS_EXPORT MutexCounter : public Mutex
00403 {
00404 private:
00405 int counter;
00406
00407 public:
00408 MutexCounter();
00409 MutexCounter(int initial);
00410
00411 friend CCXX_EXPORT(int) operator++(MutexCounter &mc);
00412 friend CCXX_EXPORT(int) operator--(MutexCounter &mc);
00413 };
00414
00425 class CCXX_CLASS_EXPORT AtomicCounter
00426 {
00427 #ifndef WIN32
00428 private:
00429 #ifdef HAVE_ATOMIC
00430 atomic_t atomic;
00431 #else
00432 int counter;
00433 Mutex lock;
00434 #endif
00435
00436 public:
00440 AtomicCounter();
00441
00447 AtomicCounter(int value);
00448
00449 int operator++(void);
00450 int operator--(void);
00451 int operator+=(int change);
00452 int operator-=(int change);
00453 int operator+(int change);
00454 int operator-(int change);
00455 int operator=(int value);
00456 bool operator!(void);
00457 operator int();
00458 #else
00459 private:
00460 long atomic;
00461
00462 public:
00463 inline AtomicCounter()
00464 {atomic = 0;};
00465
00466 inline AtomicCounter(int value)
00467 {atomic = value;};
00468
00469 inline int operator++(void)
00470 {return InterlockedIncrement(&atomic);};
00471
00472 inline int operator--(void)
00473 {return InterlockedDecrement(&atomic);};
00474
00475 int operator+=(int change);
00476
00477 int operator-=(int change);
00478
00479 inline int operator+(int change)
00480 {return atomic + change;};
00481
00482 inline int operator-(int change)
00483 {return atomic - change;};
00484
00485 inline int operator=(int value)
00486 {return InterlockedExchange(&atomic, value);};
00487
00488 inline bool operator!(void)
00489 {return (atomic == 0) ? true : false;};
00490
00491 inline operator int()
00492 {return atomic;};
00493 #endif
00494 };
00495
00496
00497 #ifndef WIN32
00498
00508 class Conditional : public Mutex
00509 {
00510 private:
00511 pthread_cond_t _cond;
00512
00513 public:
00517 Conditional();
00518
00522 virtual ~Conditional();
00523
00529 void Signal(bool broadcast);
00530
00534 void Wait(timeout_t timer = 0);
00535 };
00536 #endif
00537
00555 class CCXX_CLASS_EXPORT Semaphore
00556 {
00557 private:
00558 #ifndef WIN32
00559 #ifdef _SYSV_SEMAPHORES
00560 int _semaphore;
00561 #else
00562 sem_t _semaphore;
00563 #endif
00564 #else // WIN32
00565 HANDLE semObject;
00566 #endif // !WIN32
00567
00568 public:
00577 Semaphore(size_t resource = 0);
00578
00585 virtual ~Semaphore();
00586
00600 void Wait(void);
00601
00613 bool TryWait(void);
00614
00626 void Post(void);
00627
00628
00634 #ifndef WIN32
00635 #ifndef __CYGWIN32__
00636 int getValue(void);
00637 #endif
00638 #endif
00639 };
00640
00654 class CCXX_CLASS_EXPORT Event
00655 {
00656 private:
00657 #ifndef WIN32
00658 Mutex mutex;
00659 pthread_cond_t _cond;
00660 bool _signaled;
00661 int _count;
00662 #else
00663 HANDLE cond;
00664 #endif
00665
00666 public:
00667 Event();
00668
00669 virtual ~Event();
00670
00677 void Reset(void);
00678
00682 void Signal(void);
00683
00692 bool Wait(timeout_t timer);
00693 bool Wait(void);
00694 };
00695
00717 class CCXX_CLASS_EXPORT Buffer
00718 {
00719 private:
00720 Mutex lock_head, lock_tail;
00721 Semaphore size_head, size_tail;
00722 size_t _size;
00723 size_t _used;
00724
00725 protected:
00731 virtual int OnPeek(void *buf) = 0;
00737 virtual int OnWait(void *buf) = 0;
00743 virtual int OnPost(void *buf) = 0;
00744
00745 public:
00750 Buffer(size_t capacity);
00755 virtual ~Buffer()
00756 {return;};
00757
00762 inline size_t getSize(void)
00763 {return _size;};
00764
00771 inline size_t getUsed(void)
00772 {return _used;};
00773
00782 int Wait(void *buf);
00783
00791 int Post(void *buf);
00792
00799 int Peek(void *buf);
00800
00805 virtual bool isValid(void)
00806 {return true;};
00807 };
00808
00816 class CCXX_CLASS_EXPORT FixedBuffer : public Buffer
00817 {
00818 private:
00819 char *buf, *head, *tail;
00820 size_t objsize;
00821
00822 protected:
00828 int OnPeek(void *buf);
00829
00835 int OnWait(void *buf);
00836
00842 int OnPost(void *buf);
00843
00844 public:
00852 FixedBuffer(size_t capacity, size_t objsize);
00853
00860 FixedBuffer(const FixedBuffer &fb);
00861
00865 virtual ~FixedBuffer();
00866
00867 FixedBuffer &operator=(const FixedBuffer &fb);
00868
00869 bool isValid(void);
00870 };
00871
01019 class Thread
01020 {
01021 #ifndef WIN32
01022 friend class PosixThread;
01023 friend RETSIGTYPE ccxx_sigsuspend(int);
01024 #endif
01025 private:
01026 friend class Slog;
01027
01028 static Thread *_main;
01029
01030 Thread *_parent;
01031 #ifndef WIN32
01032 pthread_t _tid;
01033 pthread_attr_t _attr;
01034 AtomicCounter _suspendcount;
01035 #else
01036 DWORD _tid;
01037 HANDLE _cancellation;
01038 #endif
01039 thread_cancel_t _cancel;
01040 jmp_buf _env;
01041 Semaphore *_start;
01042 int _msgpos;
01043 char _msgbuf[128];
01044 throw_t _throw;
01045
01046 #ifndef WIN32
01047 friend void execHandler(Thread *th);
01048 friend Thread *getThread(void);
01049 #else
01050 bool _active:1;
01051 bool _suspendEnable:1;
01052 static unsigned __stdcall Execute(Thread *th);
01053 HANDLE _hThread;
01054 #endif
01055
01056 protected:
01066 virtual void Run(void) = 0;
01067
01080 CCXX_MEMBER_EXPORT(virtual void) Final(void)
01081 {return;};
01082
01093 CCXX_MEMBER_EXPORT(virtual void) Initial(void)
01094 {return;};
01095
01105 CCXX_MEMBER_EXPORT(virtual void*) getExtended(void)
01106 {return NULL;};
01107
01115 CCXX_MEMBER_EXPORT(virtual void) Notify(Thread *th)
01116 {return;};
01117
01127 CCXX_MEMBER_EXPORT(void) Sleep(timeout_t msec)
01128 #ifndef WIN32
01129 {ccxx_sleep(msec);}
01130 #endif
01131 ;
01132
01138 inline void Exit(void)
01139 {longjmp(_env, 1);};
01140
01145 CCXX_MEMBER_EXPORT(void) Yield(void);
01146
01150 CCXX_MEMBER_EXPORT(void) testCancel(void);
01151
01160 CCXX_MEMBER_EXPORT(void) setCancel(thread_cancel_t mode);
01161
01169 CCXX_MEMBER_EXPORT(void) setSuspend(thread_suspend_t mode);
01170
01179 CCXX_MEMBER_EXPORT(void) Terminate(void);
01180
01184 inline void clrParent(void)
01185 {_parent = NULL;};
01186
01187 #ifdef WIN32
01188
01189 CCXX_MEMBER_EXPORT(DWORD) WaitHandle(HANDLE obj, timeout_t timeout);
01190 #endif
01191
01192 public:
01201 CCXX_MEMBER_EXPORT(CCXX_EMPTY) Thread(bool isMain);
01202
01215 CCXX_MEMBER_EXPORT(CCXX_EMPTY) Thread(int pri = 0, size_t stack = 0);
01216
01217
01218 #ifndef WIN32
01219
01226 Thread(const Thread &th);
01227 #endif
01228
01235 CCXX_MEMBER_EXPORT(virtual) ~Thread()
01236 {Terminate();};
01237
01250 CCXX_MEMBER_EXPORT(int) Start(Semaphore *start = 0);
01251
01260 CCXX_MEMBER_EXPORT(int) Detach(Semaphore *start = 0);
01261
01268 inline Thread *getParent(void)
01269 {return _parent;};
01270
01277 CCXX_MEMBER_EXPORT(void) Suspend(void);
01278
01282 CCXX_MEMBER_EXPORT(void) Resume(void);
01283
01290 inline thread_cancel_t getCancel(void)
01291 {return _cancel;};
01292
01299 bool isRunning(void)
01300 #ifdef WIN32
01301 {return (_tid != 0) ? true : false;}
01302 #endif
01303 ;
01304
01311 bool isThread(void)
01312 #ifdef WIN32
01313 {return ((_tid == GetCurrentThreadId())) ? true : false;}
01314 #endif
01315 ;
01316
01322 friend CCXX_EXPORT(throw_t) getException(void);
01323
01329 friend CCXX_EXPORT(void) setException(throw_t mode);
01330
01334 friend inline int start(Thread &th, Semaphore *start = 0)
01335 {return th.Start(start);};
01336
01343 friend inline void operator++(Thread &th)
01344 {th._start->Post();};
01345
01346 friend inline void operator--(Thread &th)
01347 {th._start->Wait();};
01348
01354 friend CCXX_EXPORT(void) ccxx_sleep(timeout_t msec);
01355
01356 #ifdef WIN32
01357
01358 inline bool isCancelled(void)
01359 {return waitThread(_cancellation, 0) == WAIT_OBJECT_0; };
01360
01361 inline bool isCancelled(timeout_t timer)
01362 {return waitThread(_cancellation, timer) == WAIT_OBJECT_0; };
01363
01364 friend CCXX_EXPORT(DWORD) waitThread(HANDLE hRef, timeout_t timeout);
01365 friend CCXX_EXPORT(void) ccxx_yield(void);
01366 #endif
01367 };
01368
01374 inline void suspend(Thread &th)
01375 { th.Suspend(); }
01376
01382 inline void resume(Thread &th)
01383 { th.Resume(); }
01384
01385 #ifndef WIN32
01386 extern "C" void sigHandler(int signo);
01387
01388 typedef int signo_t;
01389
01390 class PosixThread: public Thread
01391 {
01392 private:
01393 #ifndef WIN32
01394 friend void execHandler(Thread *th);
01395 #endif
01396 #ifndef _SIG_THREAD_ALARM
01397 static PosixThread *_timer;
01398 static Mutex _arm;
01399 #endif
01400
01401 time_t _alarm;
01402 friend void sigHandler(int signo);
01403 inline static void SignalThread(Thread* th,signo_t signo)
01404 {pthread_kill(th->_tid, signo);};
01405 protected:
01406
01413 inline void SignalParent(signo_t signo)
01414 { SignalThread(_parent,signo); };
01415
01422 inline void SignalMain(signo_t signo)
01423 { SignalThread(_main,signo);};
01424
01429 virtual void OnTimer(void)
01430 {return;};
01431
01436 virtual void OnHangup(void)
01437 {return;};
01438
01443 virtual void OnException(void)
01444 {return;};
01445
01450 virtual void OnDisconnect(void)
01451 {return;};
01452
01457 virtual void OnPolling(void)
01458 {return;};
01459
01466 virtual void OnSignal(int signo)
01467 {return;};
01468
01478 void setTimer(timeout_t timer);
01479
01486 timeout_t getTimer(void);
01487
01493 void endTimer(void);
01494
01501 void WaitSignal(signo_t signo);
01502
01509 void setSignal(int signo, bool mode);
01510 public:
01511
01517 inline void SignalThread(int signo)
01518 {SignalThread(this, signo);};
01519
01526 friend void siginstall(int signo);
01527 };
01528 inline void signal(PosixThread &th, int signo)
01529 {th.SignalThread(signo);};
01530 #endif
01531
01546 class CCXX_CLASS_EXPORT ThreadKey
01547 {
01548 private:
01549 #ifndef WIN32
01550 pthread_key_t key;
01551 #else
01552 DWORD key;
01553 #endif
01554
01555 public:
01559 ThreadKey();
01563 virtual ~ThreadKey();
01571 void *getKey(void);
01579 void setKey(void *);
01580 };
01581
01592 class CCXX_CLASS_EXPORT TimerPort
01593 {
01594 #ifndef WIN32
01595 struct timeval timer;
01596 #else
01597 DWORD timer;
01598 #endif
01599 bool active;
01600
01601 public:
01608 TimerPort();
01609
01618 void setTimer(timeout_t timeout = 0);
01619
01629 void incTimer(timeout_t timeout);
01630
01636 void endTimer(void);
01637
01648 timeout_t getTimer(void);
01649
01658 timeout_t getElapsed(void);
01659 };
01660
01661
01662
01663
01664 #undef signal
01665
01666 inline void *getKey(ThreadKey &tk)
01667 {return tk.getKey();};
01668
01669 inline void setKey(ThreadKey &tk, void *ptr)
01670 {tk.setKey(ptr);};
01671
01672 inline void operator++(Mutex &m)
01673 {m.EnterMutex();};
01674
01675 inline void operator--(Mutex &m)
01676 {m.LeaveMutex();};
01677
01678 inline void operator++(Semaphore &s)
01679 {s.Post();};
01680
01681 inline void operator--(Semaphore &s)
01682 {s.Wait();};
01683
01684 inline void operator ++(Event &s)
01685 {s.Signal();};
01686
01687 inline void operator --(Event &s)
01688 {s.Wait();};
01689
01690 inline void signal(Event &ev)
01691 {ev.Signal();};
01692
01693 inline void wait(Event &ev)
01694 {ev.Wait();};
01695
01696 inline void wait(Event &ev, timeout_t timer)
01697 {ev.Wait(timer);};
01698
01699 inline void reset(Event &ev)
01700 {ev.Reset();};
01701
01702 inline void signal(Semaphore &sem)
01703 {sem.Post();};
01704
01705 inline void wait(Semaphore &sem)
01706 {sem.Wait();};
01707
01708 inline int get(Buffer &b, void *o)
01709 {return b.Wait(o);};
01710
01711 inline int put(Buffer &b, void *o)
01712 {return b.Post(o);};
01713
01714 inline int peek(Buffer &b, void *o)
01715 {return b.Peek(o);};
01716
01717
01718
01719 #ifndef WIN32
01720
01721 struct timespec *gettimeout(struct timespec *spec, timeout_t timeout);
01722 void wait(signo_t signo);
01731 void pdetach(void);
01732 #endif // !WIN32
01733
01734
01735 #ifndef WIN32
01736 #if defined(HAVE_POLL_H) || defined(HAVE_SYS_POLL_H)
01737 #if defined(HAVE_SYS_STREAM_H)
01738 #if defined(__linux__)
01739 #define __CCXX_USE_POLL 1
01740 #endif
01741 #else
01742 #define __CCXX_USE_POLL 1
01743 #endif
01744 #endif
01745
01746 #ifdef __CCXX_USE_POLL
01747
01755 class Poller
01756 {
01757 private:
01758 int nufds;
01759 pollfd *ufds;
01760
01761 public:
01762 Poller();
01763
01764 virtual ~Poller();
01765
01773 pollfd *getList(int cnt);
01774
01780 inline pollfd *getList(void)
01781 {return ufds;};
01782 };
01783 #endif
01784 #endif // !WIN32
01785
01786 #ifdef COMMON_STD_EXCEPTION
01787
01793 class ThrException : public Exception
01794 {
01795 public:
01796 ThrException(const std::string &what_arg) : Exception(what_arg) {};
01797 };
01798
01805 class SyncException : public ThrException
01806 {
01807 public:
01808 SyncException(const std::string &what_arg) : ThrException(what_arg) {};
01809 };
01810 #endif
01811
01812 #ifdef __NAMESPACES__
01813 };
01814 #endif
01815
01816 #endif
01817