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 #endif // !WIN32
00047
00048 #ifndef CCXX_CONFIG_H_
00049 #include <cc++/config.h>
00050 #endif
00051
00052 #ifndef CCXX_EXCEPTION_H_
00053 #include <cc++/exception.h>
00054 #endif
00055
00056 #ifndef WIN32
00057 #if defined(__FreeBSD__) && __FreeBSD__ <= 3
00058 #define CCXX_SYSV_SEMAPHORES
00059 #endif
00060
00061 #ifndef HAVE_PTHREAD_H
00062 #include <pthread.h>
00063 #ifndef CCXX_SYSV_SEMAPHORES
00064 #include <semaphore.h>
00065 #endif
00066 #endif
00067 #endif // !WIN32
00068
00069 #include <setjmp.h>
00070
00071 #ifndef WIN32
00072 #include <time.h>
00073 #include <signal.h>
00074 #include <unistd.h>
00075
00076 #ifdef __linux__
00077 #define CCXX_SIG_THREAD_ALARM
00078 #define CCXX_SIG_THREAD_STOPCONT
00079 #endif
00080
00081 #ifdef _THR_UNIXWARE
00082 #undef PTHREAD_MUTEXTYPE_RECURSIVE
00083 #endif
00084
00085 typedef pthread_t cctid_t;
00086 typedef unsigned long timeout_t;
00087 #else // WIN32
00088 typedef DWORD cctid_t;
00089 typedef DWORD timeout_t;
00090
00091 #define MAX_SEM_VALUE 1000000
00092 #if defined(__MINGW32__) || defined(__CYGWIN32__)
00093 #include <Windows32/CommonFunctions.h>
00094 #else
00095 __declspec(dllimport) long __stdcall InterlockedIncrement(long *);
00096 __declspec(dllimport) long __stdcall InterlockedDecrement(long *);
00097 __declspec(dllimport) long __stdcall InterlockedExchange(long *, long);
00098 #endif
00099
00100 #endif // !WIN32
00101
00102 #ifdef CCXX_NAMESPACES
00103 namespace ost {
00104 #endif
00105
00106 enum throw_t {
00107 THROW_NOTHING,
00108 THROW_OBJECT,
00109 THROW_EXCEPTION
00110 };
00111 typedef enum throw_t throw_t;
00112 class Thread;
00113
00114 #define TIMEOUT_INF ~((timeout_t) 0)
00115
00116 #define ENTER_CRITICAL EnterMutex();
00117 #define LEAVE_CRITICAL LeaveMutex();
00118 #define ENTER_DEFERRED setCancel(THREAD_CANCEL_DEFERRED);
00119 #define LEAVE_DEFERRED setCancel(THREAD_CANCEL_IMMEDIATE);
00120
00121 enum thread_cancel_t
00122 {
00123 THREAD_CANCEL_INITIAL=0,
00124 THREAD_CANCEL_DEFERRED=1,
00125 THREAD_CANCEL_IMMEDIATE,
00126 THREAD_CANCEL_DISABLED,
00127 THREAD_CANCEL_DEFAULT=THREAD_CANCEL_DEFERRED
00128 };
00129 typedef enum thread_cancel_t thread_cancel_t;
00130
00131 enum thread_suspend_t
00132 {
00133 THREAD_SUSPEND_ENABLE,
00134 THREAD_SUSPEND_DISABLE
00135 };
00136 typedef enum thread_suspend_t thread_suspend_t;
00137
00138 #ifndef WIN32
00139
00140
00141
00142
00143
00144
00145 #undef sleep
00146 #define psleep(x) (sleep)(x)
00147
00148 #ifndef CCXX_SIG_THREAD_STOPCONT
00149 #ifndef _THR_SUNOS5
00150 #ifndef HAVE_PTHREAD_SUSPEND
00151 static RETSIGTYPE ccxx_sigsuspend(int);
00152 #endif
00153 #endif
00154 #endif
00155 extern "C" void execHandler(Thread *th);
00156
00157 #endif // !WIN32
00158
00159
00160 CCXX_EXPORT(Thread*) getThread(void);
00161 CCXX_EXPORT(throw_t) getException(void);
00162 CCXX_EXPORT(void) setException(throw_t mode);
00163 CCXX_EXPORT(void) ccxx_sleep(timeout_t msec);
00164 CCXX_EXPORT(void) ccxx_yield(void);
00165
00166 #undef Yield
00167 #define sleep(x) ccxx_sleep((x) * 1000)
00168 #define yield() ccxx_yield()
00169
00170 #ifdef WIN32
00171 CCXX_EXPORT(DWORD) waitThread(HANDLE hRef, timeout_t timeout);
00172 #endif
00173
00174 class Conditional;
00175 class CCXX_CLASS_EXPORT Event;
00176
00220 class CCXX_CLASS_EXPORT Mutex
00221 {
00222 friend class Conditional;
00223 friend class Event;
00224 private:
00225 #ifndef WIN32
00226 #ifndef PTHREAD_MUTEXTYPE_RECURSIVE
00227 volatile int _level;
00228 volatile Thread *_tid;
00229 #endif
00230
00238 pthread_mutex_t _mutex;
00239 #else
00240 HANDLE mutex;
00241 #endif
00242
00243 public:
00247 Mutex();
00248
00254 virtual ~Mutex();
00255
00263 void EnterMutex(void);
00264
00275 bool TryEnterMutex(void);
00276
00287 void LeaveMutex(void);
00288 };
00289
00311 class MutexLock
00312 {
00313 private:
00314 Mutex& mutex;
00315 public:
00319 MutexLock( Mutex& _mutex ) : mutex( _mutex )
00320 { mutex.EnterMutex(); }
00324
00325 ~MutexLock()
00326 { mutex.LeaveMutex(); }
00327 };
00328
00337 class CCXX_CLASS_EXPORT ThreadLock
00338 {
00339 private:
00340 #ifdef HAVE_PTHREAD_RWLOCK
00341 pthread_rwlock_t _lock;
00342 #else
00343 Mutex mutex;
00344 #endif
00345
00346 public:
00350 ThreadLock();
00351
00355 virtual ~ThreadLock();
00356
00360 void ReadLock(void);
00361
00365 void WriteLock(void);
00366
00372 bool TryReadLock(void);
00373
00379 bool TryWriteLock(void);
00380
00384 void Unlock(void);
00385 };
00386
00396 class CCXX_CLASS_EXPORT MutexCounter : public Mutex
00397 {
00398 private:
00399 int counter;
00400
00401 public:
00402 MutexCounter();
00403 MutexCounter(int initial);
00404
00405 friend CCXX_EXPORT(int) operator++(MutexCounter &mc);
00406 friend CCXX_EXPORT(int) operator--(MutexCounter &mc);
00407 };
00408
00419 class CCXX_CLASS_EXPORT AtomicCounter
00420 {
00421 #ifndef WIN32
00422 private:
00423 #ifdef HAVE_ATOMIC
00424 atomic_t atomic;
00425 #else
00426 int counter;
00427 Mutex lock;
00428 #endif
00429
00430 public:
00434 AtomicCounter();
00435
00441 AtomicCounter(int value);
00442
00443 int operator++(void);
00444 int operator--(void);
00445 int operator+=(int change);
00446 int operator-=(int change);
00447 int operator+(int change);
00448 int operator-(int change);
00449 int operator=(int value);
00450 bool operator!(void);
00451 operator int();
00452 #else
00453 private:
00454 long atomic;
00455
00456 public:
00457 inline AtomicCounter()
00458 {atomic = 0;};
00459
00460 inline AtomicCounter(int value)
00461 {atomic = value;};
00462
00463 inline int operator++(void)
00464 {return InterlockedIncrement(&atomic);};
00465
00466 inline int operator--(void)
00467 {return InterlockedDecrement(&atomic);};
00468
00469 int operator+=(int change);
00470
00471 int operator-=(int change);
00472
00473 inline int operator+(int change)
00474 {return atomic + change;};
00475
00476 inline int operator-(int change)
00477 {return atomic - change;};
00478
00479 inline int operator=(int value)
00480 {return InterlockedExchange(&atomic, value);};
00481
00482 inline bool operator!(void)
00483 {return (atomic == 0) ? true : false;};
00484
00485 inline operator int()
00486 {return atomic;};
00487 #endif
00488 };
00489
00490
00491 #ifndef WIN32
00492
00502 class Conditional : public Mutex
00503 {
00504 private:
00505 pthread_cond_t _cond;
00506
00507 public:
00511 Conditional();
00512
00516 virtual ~Conditional();
00517
00523 void Signal(bool broadcast);
00524
00528 void Wait(timeout_t timer = 0);
00529 };
00530 #endif
00531
00549 class CCXX_CLASS_EXPORT Semaphore
00550 {
00551 private:
00552 #ifndef WIN32
00553 #ifdef CCXX_SYSV_SEMAPHORES
00554 int _semaphore;
00555 #else
00556 sem_t _semaphore;
00557 #endif
00558 #else // WIN32
00559 HANDLE semObject;
00560 #endif // !WIN32
00561
00562 public:
00571 Semaphore(size_t resource = 0);
00572
00579 virtual ~Semaphore();
00580
00594 void Wait(void);
00595
00607 bool TryWait(void);
00608
00620 void Post(void);
00621
00622
00628 #ifndef WIN32
00629 #ifndef __CYGWIN32__
00630 int getValue(void);
00631 #endif
00632 #endif
00633 };
00634
00648 class CCXX_CLASS_EXPORT Event
00649 {
00650 private:
00651 #ifndef WIN32
00652 Mutex mutex;
00653 pthread_cond_t _cond;
00654 bool _signaled;
00655 int _count;
00656 #else
00657 HANDLE cond;
00658 #endif
00659
00660 public:
00661 Event();
00662
00663 virtual ~Event();
00664
00671 void Reset(void);
00672
00676 void Signal(void);
00677
00686 bool Wait(timeout_t timer);
00687 bool Wait(void);
00688 };
00689
00711 class CCXX_CLASS_EXPORT Buffer
00712 {
00713 private:
00714 Mutex lock_head, lock_tail;
00715 Semaphore size_head, size_tail;
00716 size_t _size;
00717 size_t _used;
00718
00719 protected:
00725 virtual int OnPeek(void *buf) = 0;
00731 virtual int OnWait(void *buf) = 0;
00737 virtual int OnPost(void *buf) = 0;
00738
00739 public:
00744 Buffer(size_t capacity);
00749 virtual ~Buffer()
00750 {return;};
00751
00756 inline size_t getSize(void)
00757 {return _size;};
00758
00765 inline size_t getUsed(void)
00766 {return _used;};
00767
00776 int Wait(void *buf);
00777
00785 int Post(void *buf);
00786
00793 int Peek(void *buf);
00794
00799 virtual bool isValid(void)
00800 {return true;};
00801 };
00802
00810 class CCXX_CLASS_EXPORT FixedBuffer : public Buffer
00811 {
00812 private:
00813 char *buf, *head, *tail;
00814 size_t objsize;
00815
00816 protected:
00822 int OnPeek(void *buf);
00823
00829 int OnWait(void *buf);
00830
00836 int OnPost(void *buf);
00837
00838 public:
00846 FixedBuffer(size_t capacity, size_t objsize);
00847
00854 FixedBuffer(const FixedBuffer &fb);
00855
00859 virtual ~FixedBuffer();
00860
00861 FixedBuffer &operator=(const FixedBuffer &fb);
00862
00863 bool isValid(void);
00864 };
00865
01013 class Thread
01014 {
01015 #ifndef WIN32
01016 friend class PosixThread;
01017 friend RETSIGTYPE ccxx_sigsuspend(int);
01018 #endif
01019 private:
01020 friend class Slog;
01021
01022 static Thread *_main;
01023
01024 Thread *_parent;
01025 #ifndef WIN32
01026 pthread_t _tid;
01027 pthread_attr_t _attr;
01028 AtomicCounter _suspendcount;
01029 #else
01030 DWORD _tid;
01031 HANDLE _cancellation;
01032 #endif
01033 thread_cancel_t _cancel;
01034 jmp_buf _env;
01035 Semaphore *_start;
01036 int _msgpos;
01037 char _msgbuf[128];
01038 throw_t _throw;
01039
01040 #ifndef WIN32
01041 friend void execHandler(Thread *th);
01042 friend Thread *getThread(void);
01043 #else
01044 bool _active:1;
01045 bool _suspendEnable:1;
01046 static unsigned __stdcall Execute(Thread *th);
01047 HANDLE _hThread;
01048 #endif
01049
01050 protected:
01060 virtual void Run(void) = 0;
01061
01074 CCXX_MEMBER_EXPORT(virtual void) Final(void)
01075 {return;};
01076
01087 CCXX_MEMBER_EXPORT(virtual void) Initial(void)
01088 {return;};
01089
01099 CCXX_MEMBER_EXPORT(virtual void*) getExtended(void)
01100 {return NULL;};
01101
01109 CCXX_MEMBER_EXPORT(virtual void) Notify(Thread *th)
01110 {return;};
01111
01121 CCXX_MEMBER_EXPORT(void) Sleep(timeout_t msec)
01122 #ifndef WIN32
01123 {ccxx_sleep(msec);}
01124 #endif
01125 ;
01126
01127
01133 inline void Exit(void)
01134 {longjmp(_env, 1);};
01135
01140 CCXX_MEMBER_EXPORT(void) Yield(void);
01141
01145 CCXX_MEMBER_EXPORT(void) testCancel(void);
01146
01155 CCXX_MEMBER_EXPORT(void) setCancel(thread_cancel_t mode);
01156
01164 CCXX_MEMBER_EXPORT(void) setSuspend(thread_suspend_t mode);
01165
01174 CCXX_MEMBER_EXPORT(void) Terminate(void);
01175
01179 inline void clrParent(void)
01180 {_parent = NULL;};
01181
01182 #ifdef WIN32
01183
01184 CCXX_MEMBER_EXPORT(DWORD) WaitHandle(HANDLE obj, timeout_t timeout);
01185 #endif
01186
01187 public:
01196 CCXX_MEMBER_EXPORT(CCXX_EMPTY) Thread(bool isMain);
01197
01210 CCXX_MEMBER_EXPORT(CCXX_EMPTY) Thread(int pri = 0, size_t stack = 0);
01211
01212
01213 #ifndef WIN32
01214
01221 Thread(const Thread &th);
01222 #endif
01223
01230 CCXX_MEMBER_EXPORT(virtual) ~Thread()
01231 {Terminate();};
01232
01245 CCXX_MEMBER_EXPORT(int) Start(Semaphore *start = 0);
01246
01255 CCXX_MEMBER_EXPORT(int) Detach(Semaphore *start = 0);
01256
01263 inline Thread *getParent(void)
01264 {return _parent;};
01265
01272 CCXX_MEMBER_EXPORT(void) Suspend(void);
01273
01277 CCXX_MEMBER_EXPORT(void) Resume(void);
01278
01285 inline thread_cancel_t getCancel(void)
01286 {return _cancel;};
01287
01294 bool isRunning(void)
01295 #ifdef WIN32
01296 {return (_tid != 0) ? true : false;}
01297 #endif
01298 ;
01299
01306 bool isThread(void)
01307 #ifdef WIN32
01308 {return ((_tid == GetCurrentThreadId())) ? true : false;}
01309 #endif
01310 ;
01311
01317 friend CCXX_EXPORT(throw_t) getException(void);
01318
01324 friend CCXX_EXPORT(void) setException(throw_t mode);
01325
01326
01333 friend inline void operator++(Thread &th)
01334 {th._start->Post();};
01335
01336 friend inline void operator--(Thread &th)
01337 {th._start->Wait();};
01338
01344 friend CCXX_EXPORT(void) ccxx_sleep(timeout_t msec);
01345
01349 friend CCXX_EXPORT(void) ccxx_yield(void);
01350
01351 #ifdef WIN32
01352
01353 inline bool isCancelled(void)
01354 {return waitThread(_cancellation, 0) == WAIT_OBJECT_0; };
01355
01356 inline bool isCancelled(timeout_t timer)
01357 {return waitThread(_cancellation, timer) == WAIT_OBJECT_0; };
01358
01359 friend CCXX_EXPORT(DWORD) waitThread(HANDLE hRef, timeout_t timeout);
01360 #endif
01361 };
01362
01363 #if !defined(WIN32) && !defined(__CYGWIN32__) && !defined(__MINGW32__)
01364 extern "C" void sigHandler(int signo);
01365
01366 typedef int signo_t;
01367
01368 class PosixThread: public Thread
01369 {
01370 private:
01371 #ifndef WIN32
01372 friend void execHandler(Thread *th);
01373 #endif
01374 #ifndef CCXX_SIG_THREAD_ALARM
01375 static PosixThread *_timer;
01376 static Mutex _arm;
01377 #endif
01378
01379 time_t _alarm;
01380 friend void sigHandler(int signo);
01381 inline static void SignalThread(Thread* th,signo_t signo)
01382 {pthread_kill(th->_tid, signo);};
01383 protected:
01384
01391 inline void SignalParent(signo_t signo)
01392 { SignalThread(_parent,signo); };
01393
01400 inline void SignalMain(signo_t signo)
01401 { SignalThread(_main,signo);};
01402
01407 virtual void OnTimer(void)
01408 {return;};
01409
01414 virtual void OnHangup(void)
01415 {return;};
01416
01421 virtual void OnException(void)
01422 {return;};
01423
01428 virtual void OnDisconnect(void)
01429 {return;};
01430
01435 virtual void OnPolling(void)
01436 {return;};
01437
01444 virtual void OnSignal(int signo)
01445 {return;};
01446
01456 void setTimer(timeout_t timer);
01457
01464 timeout_t getTimer(void);
01465
01471 void endTimer(void);
01472
01479 void WaitSignal(signo_t signo);
01480
01487 void setSignal(int signo, bool mode);
01488 public:
01489
01495 inline void SignalThread(int signo)
01496 {SignalThread(this, signo);};
01497
01504 friend void siginstall(int signo);
01505 };
01506 #endif
01507
01522 class CCXX_CLASS_EXPORT ThreadKey
01523 {
01524 private:
01525 #ifndef WIN32
01526 pthread_key_t key;
01527 #else
01528 DWORD key;
01529 #endif
01530
01531 public:
01535 ThreadKey();
01539 virtual ~ThreadKey();
01547 void *getKey(void);
01555 void setKey(void *);
01556 };
01557
01568 class CCXX_CLASS_EXPORT TimerPort
01569 {
01570 #ifndef WIN32
01571 struct timeval timer;
01572 #else
01573 DWORD timer;
01574 #endif
01575 bool active;
01576
01577 public:
01584 TimerPort();
01585
01594 void setTimer(timeout_t timeout = 0);
01595
01605 void incTimer(timeout_t timeout);
01606
01612 void endTimer(void);
01613
01624 timeout_t getTimer(void);
01625
01634 timeout_t getElapsed(void);
01635 };
01636
01637 inline int get(Buffer &b, void *o)
01638 {return b.Wait(o);};
01639
01640 inline int put(Buffer &b, void *o)
01641 {return b.Post(o);};
01642
01643 inline int peek(Buffer &b, void *o)
01644 {return b.Peek(o);};
01645
01646
01647
01648 #if !defined(WIN32)
01649
01650
01651 struct timespec *gettimeout(struct timespec *spec, timeout_t timeout);
01652
01653 #if !defined(__CYGWIN32__) && !defined(__MINGW32__)
01654 void wait(signo_t signo);
01655 #endif
01656
01665 void pdetach(void);
01666 #endif // !WIN32
01667
01668
01669 #ifndef WIN32
01670 #if defined(HAVE_POLL_H) || defined(HAVE_SYS_POLL_H)
01671 #if defined(HAVE_SYS_STREAM_H)
01672 #if defined(__linux__)
01673 #define CCXX_USE_POLL 1
01674 #endif
01675 #else
01676 #define CCXX_USE_POLL 1
01677 #endif
01678 #endif
01679
01680 #ifdef CCXX_USE_POLL
01681
01689 class Poller
01690 {
01691 private:
01692 int nufds;
01693 pollfd *ufds;
01694
01695 public:
01696 Poller();
01697
01698 virtual ~Poller();
01699
01707 pollfd *getList(int cnt);
01708
01714 inline pollfd *getList(void)
01715 {return ufds;};
01716 };
01717 #endif
01718 #endif // !WIN32
01719
01720 #ifdef COMMON_STD_EXCEPTION
01721
01727 class ThrException : public Exception
01728 {
01729 public:
01730 ThrException(const std::string &what_arg) : Exception(what_arg) {};
01731 };
01732
01739 class SyncException : public ThrException
01740 {
01741 public:
01742 SyncException(const std::string &what_arg) : ThrException(what_arg) {};
01743 };
01744 #endif
01745
01746 #ifdef CCXX_NAMESPACES
01747 };
01748 #endif
01749
01750 #endif
01751