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
00046
#ifndef CCXX_THREAD_H_
00047
#define CCXX_THREAD_H_
00048
00049
#ifndef WIN32
00050 #define CCXX_POSIX
00051
#endif // !WIN32
00052
00053
#ifndef CCXX_CONFIG_H_
00054
#include <cc++/config.h>
00055
#endif
00056
00057
#include <ctime>
00058
00059
#ifndef WIN32
00060
#include <pthread.h>
00061
#endif // !WIN32
00062
00063
#undef CCXX_USE_WIN32_ATOMIC
00064
#ifndef WIN32
00065
#include <time.h>
00066
#include <signal.h>
00067
#include <unistd.h>
00068
00069
#ifdef _THR_UNIXWARE
00070
#undef PTHREAD_MUTEXTYPE_RECURSIVE
00071
#endif
00072
00073 typedef pthread_t
cctid_t;
00074 typedef unsigned long timeout_t;
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
#else // WIN32
00086
typedef DWORD
cctid_t;
00087
typedef DWORD
timeout_t;
00088
00089
#define MAX_SEM_VALUE 1000000
00090
#define CCXX_USE_WIN32_ATOMIC 1
00091
00092
#endif // !WIN32
00093
00094
#ifdef CCXX_NAMESPACES
00095
namespace ost {
00096
#endif
00097
00098 class __EXPORT
Thread;
00099 class __EXPORT
ThreadKey;
00100
00101 #define TIMEOUT_INF ~((timeout_t) 0)
00102
00103 #define ENTER_CRITICAL enterMutex();
00104 #define LEAVE_CRITICAL leaveMutex();
00105 #define ENTER_DEFERRED setCancel(cancelDeferred);
00106 #define LEAVE_DEFERRED setCancel(cancelImmediate);
00107
00108
#ifndef WIN32
00109
00110
00111
00112
00113
00114
00115
#undef sleep
00116 #define psleep(x) (sleep)(x)
00117
00118
#ifdef signal
00119
#undef signal
00120
#endif
00121
00122
#endif // !WIN32
00123
00124
#undef Yield
00125
00126 class __EXPORT
Conditional;
00127 class __EXPORT
Event;
00128
00172 class __EXPORT Mutex
00173 {
00174
private:
00175
static bool _debug;
00176
const char *_name;
00177
#ifndef WIN32
00178
#ifndef PTHREAD_MUTEXTYPE_RECURSIVE
00179
int volatile _level;
00180
Thread *
volatile _tid;
00181
#endif
00182
00183
00184
00185
00186
00187
00188
00189
00190 pthread_mutex_t _mutex;
00191
#else // WIN32
00192
00193
# if defined(MUTEX_UNDERGROUND_WIN32_MUTEX) && defined(MUTEX_UNDERGROUND_WIN32_CRITICALSECTION)
00194
# error "Can't determine underground for Mutex"
00195
# endif
00196
00197
#ifdef MUTEX_UNDERGROUND_WIN32_MUTEX
00198
HANDLE _mutex;
00199
#endif
00200
#ifdef MUTEX_UNDERGROUND_WIN32_CRITICALSECTION
00201
CRITICAL_SECTION _criticalSection;
00202
#endif
00203
00204
#endif // WIN32
00205
00206
public:
00210 Mutex(
const char *name = NULL);
00211
00217
virtual ~Mutex();
00218
00224 static void setDebug(
bool mode)
00225 {_debug = mode;};
00226
00234
void enterMutex(
void);
00235
00239 inline void enter(
void)
00240 {enterMutex();};
00241
00242 inline void leave(
void)
00243 {leaveMutex();};
00244
00245 inline bool test(
void)
00246 {
return tryEnterMutex();};
00247
00258
bool tryEnterMutex(
void);
00259
00270
void leaveMutex(
void);
00271 };
00272
00296 class __EXPORT MutexLock
00297 {
00298
private:
00299 Mutex& mutex;
00300
public:
00304 MutexLock( Mutex& _mutex ) : mutex( _mutex )
00305 { mutex.enterMutex(); }
00309
00310 ~MutexLock()
00311 { mutex.leaveMutex(); }
00312 };
00313
00322 class __EXPORT ThreadLock
00323 {
00324
private:
00325
#ifdef HAVE_PTHREAD_RWLOCK
00326
pthread_rwlock_t _lock;
00327
#else
00328
Mutex mutex;
00329
#endif
00330
00331
public:
00335 ThreadLock();
00336
00340
virtual ~ThreadLock();
00341
00345
void readLock(
void);
00346
00350
void writeLock(
void);
00351
00357
bool tryReadLock(
void);
00358
00364
bool tryWriteLock(
void);
00365
00369
void unlock(
void);
00370 };
00371
00392 class __EXPORT ReadLock
00393 {
00394
private:
00395 ThreadLock& tl;
00396
00397
public:
00401 ReadLock( ThreadLock& _tl ) : tl( _tl )
00402 { tl.readLock(); }
00406
00407 ~ReadLock()
00408 { tl.unlock(); }
00409 };
00410
00431 class __EXPORT WriteLock
00432 {
00433
private:
00434 ThreadLock& tl;
00435
00436
public:
00440 WriteLock( ThreadLock& _tl ) : tl( _tl )
00441 { tl.writeLock(); }
00445
00446 ~WriteLock()
00447 { tl.unlock(); }
00448 };
00449
00450
00460 class __EXPORT MutexCounter :
public Mutex
00461 {
00462
private:
00463
volatile int counter;
00464
00465
public:
00466 MutexCounter(
const char *
id = NULL);
00467 MutexCounter(
int initial,
const char *
id = NULL);
00468
00469
friend __EXPORT
int operator++(MutexCounter &mc);
00470
friend __EXPORT
int operator--(MutexCounter &mc);
00471 };
00472
00483 class __EXPORT AtomicCounter
00484 {
00485
#ifndef CCXX_USE_WIN32_ATOMIC
00486
private:
00487
#ifdef HAVE_ATOMIC_AIX
00488
volatile int counter;
00489
#elif HAVE_ATOMIC
00490
atomic_t atomic;
00491
#else
00492
volatile int counter;
00493 pthread_mutex_t _mutex;
00494
#endif
00495
00496
public:
00500 AtomicCounter();
00501
00507 AtomicCounter(
int value);
00508
00509 ~AtomicCounter();
00510
00511
int operator++(
void);
00512
int operator--(
void);
00513
int operator+=(
int change);
00514
int operator-=(
int change);
00515
int operator+(
int change);
00516
int operator-(
int change);
00517
int operator=(
int value);
00518
bool operator!(
void);
00519 operator int();
00520
#else
00521
private:
00522
long atomic;
00523
00524
public:
00525
inline AtomicCounter()
00526 {atomic = 0;};
00527
00528
inline AtomicCounter(
int value)
00529 {atomic = value;};
00530
00531
inline int operator++(
void)
00532 {
return InterlockedIncrement(&atomic);};
00533
00534
inline int operator--(
void)
00535 {
return InterlockedDecrement(&atomic);};
00536
00537
int operator+=(
int change);
00538
00539
int operator-=(
int change);
00540
00541
inline int operator+(
int change)
00542 {
return atomic + change;};
00543
00544
inline int operator-(
int change)
00545 {
return atomic - change;};
00546
00547
inline int operator=(
int value)
00548 {
return InterlockedExchange(&atomic, value);};
00549
00550
inline bool operator!(
void)
00551 {
return (atomic == 0) ?
true :
false;};
00552
00553
inline operator int()
00554 {
return atomic;};
00555
#endif
00556
};
00557
00558
#ifndef WIN32
00559
00579 class __EXPORT
Conditional
00580 {
00581
private:
00582 pthread_cond_t _cond;
00583 pthread_mutex_t _mutex;
00584
00585
public:
00589
Conditional(
const char *
id = NULL);
00590
00594
virtual ~
Conditional();
00595
00601
void signal(
bool broadcast);
00602
00609
bool wait(
timeout_t timer = 0,
bool locked =
false);
00610
00617
void enterMutex(
void);
00618
00627 inline void lock(
void)
00628 {enterMutex();};
00629
00640
bool tryEnterMutex(
void);
00641
00642 inline bool test(
void)
00643 {
return tryEnterMutex();};
00644
00650
void leaveMutex(
void);
00651
00652 inline void unlock(
void)
00653 {
return leaveMutex();};
00654 };
00655
#endif
00656
00674 class __EXPORT Semaphore
00675 {
00676
private:
00677
#ifndef WIN32
00678
unsigned _count, _waiters;
00679 pthread_mutex_t _mutex;
00680 pthread_cond_t _cond;
00681
#else
00682
HANDLE semObject;
00683
#endif // !WIN32
00684
00685
public:
00694 Semaphore(
unsigned resource = 0);
00695
00702
virtual ~Semaphore();
00703
00719
bool wait(
timeout_t timeout = 0);
00720
00732
void post(
void);
00733
00734
00740
#ifndef WIN32
00741
#ifndef __CYGWIN32__
00742
int getValue(
void);
00743
#endif
00744
#endif
00745
};
00746
00766 class __EXPORT SemaphoreLock
00767 {
00768
private:
00769 Semaphore& sem;
00770
00771
public:
00775 SemaphoreLock( Semaphore& _sem ) : sem( _sem )
00776 { sem.wait(); }
00780
00781 ~SemaphoreLock()
00782 { sem.post(); }
00783 };
00784
00798 class __EXPORT
Event
00799 {
00800
private:
00801
#ifndef WIN32
00802
pthread_mutex_t _mutex;
00803 pthread_cond_t _cond;
00804
bool _signaled;
00805
int _count;
00806
#else
00807
HANDLE cond;
00808
#endif
00809
00810
public:
00811
Event();
00812
00813
virtual ~
Event();
00814
00821
void reset(
void);
00822
00826
void signal(
void);
00827
00836
bool wait(
timeout_t timer);
00837
bool wait(
void);
00838 };
00839
00840
01022 class __EXPORT
Thread
01023 {
01024
public:
01028 typedef enum Throw {
01029 throwNothing,
01030 throwObject,
01031 throwException
01032 } Throw;
01033
01037 typedef enum Cancel
01038 {
01039 cancelInitial=0,
01040 cancelDeferred=1,
01041 cancelImmediate,
01042 cancelDisabled,
01043 cancelManual,
01045 cancelDefault=cancelDeferred
01047 } Cancel;
01048
01052 typedef enum Suspend
01053 {
01054 suspendEnable,
01055 suspendDisable
01056 } Suspend;
01057
01058
#ifndef WIN32
01059
01060
friend class PosixThread;
01061
#endif
01062
01063
friend class DummyThread;
01064
private:
01065
friend class Cancellation;
01066
friend class postream_type;
01067
friend class Slog;
01068
01069 Semaphore joinSem;
01070
static Thread* _main;
01071
01072
Thread *_parent;
01073 Cancel _cancel;
01074 Semaphore *_start;
01075
01076
01077
friend class ThreadImpl;
01078
class ThreadImpl* priv;
01079
01080
public:
01081
static Thread *get(
void);
01082
01083
private:
01084
#ifdef WIN32
01085
static unsigned __stdcall Execute(Thread *th);
01086
#endif
01087
01088
01089
void close();
01090
01091
private:
01092
char _name[32];
01093
static size_t _autostack;
01094
01095
#ifdef WIN32
01096
DWORD waitHandle(
HANDLE obj, timeout_t timeout);
01097
#endif
01098
01099
protected:
01107
void setName(
const char *text);
01108
01118
virtual void run(
void) = 0;
01119
01141 virtual void final(
void)
01142 {
return;};
01143
01155 virtual void initial(
void)
01156 {
return;};
01157
01167 virtual void* getExtended(
void)
01168 {
return NULL;};
01169
01177 virtual void notify(Thread*)
01178 {
return;};
01179
01185
void exit(
void);
01186
01190
void sync(
void);
01191
01195
bool testCancel(
void);
01196
01206
void setCancel(Cancel mode);
01207
01215
void setSuspend(Suspend mode);
01216
01225
void terminate(
void);
01226
01230 inline void clrParent(
void)
01231 {_parent = NULL;};
01232
01233
public:
01242
Thread(
bool isMain);
01243
01255
Thread(
int pri = 0, size_t stack = 0);
01256
01257
#ifndef WIN32
01258
01266
Thread(
const Thread &th);
01267
#endif
01268
01275
virtual ~
Thread();
01276
01282 static void setStack(size_t size = 0)
01283 {_autostack = size;};
01284
01294
static void sleep(timeout_t msec);
01295
01300
static void yield(
void);
01301
01314
int start(Semaphore *start = 0);
01315
01324
int detach(Semaphore *start = 0);
01325
01332 inline Thread *getParent(
void)
01333 {
return _parent;};
01334
01341
void suspend(
void);
01342
01346
void resume(
void);
01347
01354 inline Cancel getCancel(
void)
01355 {
return _cancel;};
01356
01363
bool isRunning(
void);
01364
01370
bool isDetached(
void);
01371
01375
void join(
void);
01376
01383
bool isThread(
void);
01384
01390
cctid_t getId(
void) const;
01391
01398 const
char *getName(
void)
01399 {
return _name;};
01400
01406
static Throw getException(
void);
01407
01413
static void setException(Throw mode);
01414
01421 friend inline void operator++(Thread &th)
01422 {
if (th.
_start) th.
_start->
post();};
01423
01424 friend inline void operator--(Thread &th)
01425 {
if (th.
_start) th.
_start->
wait();};
01426
01427
#ifdef WIN32
01428
bool isCancelled();
01429
01430
static DWORD waitThread(
HANDLE hRef, timeout_t timeout);
01431
#endif
01432
01440
static Cancel enterCancel(
void);
01441
01447
static void exitCancel(Cancel cancel);
01448 };
01449
01459 class __EXPORT Cancellation
01460 {
01461
private:
01462
Thread::Cancel prior;
01463
01464
public:
01465 Cancellation(
Thread::Cancel cancel);
01466 ~Cancellation();
01467 };
01468
01469
#if !defined(WIN32) && !defined(__MINGW32__)
01470 typedef int signo_t;
01471
01472 class PosixThread:
public Thread
01473 {
01474
private:
01475
#ifndef WIN32
01476
01477
friend class ThreadImpl;
01478
friend class Thread;
01479
#endif
01480
#ifndef CCXX_SIG_THREAD_ALARM
01481
static PosixThread *_timer;
01482
static Mutex _arm;
01483
#endif
01484
01485 time_t _alarm;
01486
static void signalThread(
Thread* th,
signo_t signo);
01487
protected:
01488
01495 inline void signalParent(
signo_t signo)
01496 {
signalThread(_parent,signo); };
01497
01504 inline void signalMain(
signo_t signo)
01505 {
signalThread(_main,signo);};
01506
01511 virtual void onTimer(
void)
01512 {
return;};
01513
01518 virtual void onHangup(
void)
01519 {
return;};
01520
01525 virtual void onException(
void)
01526 {
return;};
01527
01532 virtual void onDisconnect(
void)
01533 {
return;};
01534
01539 virtual void onPolling(
void)
01540 {
return;};
01541
01548 virtual void onSignal(
int)
01549 {
return;};
01550
01563
void setTimer(timeout_t timer,
bool periodic =
false);
01564
01571
timeout_t getTimer(
void) const;
01572
01578
void endTimer(
void);
01579
01580 #if defined(HAVE_SIGWAIT) || defined(HAVE_SIGWAIT2)
01587
void waitSignal(
signo_t signo);
01588 #endif
01589
01596
void setSignal(
int signo,
bool active);
01597
01604 pthread_attr_t *getPthreadAttrPtr(
void);
01605
01610 pthread_t getPthreadId(
void);
01611
01612 public:
01613
01614
PosixThread(
int pri = 0, size_t stack = 0);
01615
01621 inline
void signalThread(
int signo)
01622 {
signalThread(
this, signo);};
01623
01630
static void sigInstall(
int signo);
01631 };
01632
#endif
01633
01648 class __EXPORT
ThreadKey
01649 {
01650
private:
01651
#ifndef WIN32
01652
pthread_key_t key;
01653
typedef void (*TDestruct)(
void*);
01654
friend class ThreadImpl;
01655
ThreadKey(TDestruct destruct);
01656
#else
01657
DWORD key;
01658
#endif
01659
01660
public:
01664
ThreadKey();
01668
virtual ~
ThreadKey();
01676
void *getKey(
void);
01684
void setKey(
void *);
01685 };
01686
01697 class __EXPORT TimerPort
01698 {
01699
#ifndef WIN32
01700
struct timeval timer;
01701
#else
01702
DWORD timer;
01703
#endif
01704
bool active;
01705
01706
public:
01713 TimerPort();
01714
01723
void setTimer(
timeout_t timeout = 0);
01724
01734
void incTimer(
timeout_t timeout);
01735
01741
void endTimer(
void);
01742
01754
timeout_t getTimer(
void)
const;
01755
01765
timeout_t getElapsed(
void)
const;
01766 };
01767
01768
01769
01770
01771
#if !defined(WIN32)
01772
01773
01774
struct timespec *
getTimeout(
struct timespec *spec, timeout_t timeout);
01775
01776
#if !defined(__CYGWIN32__) && !defined(__MINGW32__)
01777
void wait(
signo_t signo);
01778
#endif
01779
01780
#endif // !WIN32
01781
01782
#ifdef USE_POLL
01783
01791
class Poller
01792 {
01793
private:
01794
int nufds;
01795 pollfd *ufds;
01796
01797
public:
01798 Poller();
01799
01800
virtual ~Poller();
01801
01809 pollfd *getList(
int cnt);
01810
01816
inline pollfd *getList(
void)
01817 {
return ufds;};
01818 };
01819
#endif
01820
01821 inline Thread *
getThread(
void)
01822 {
return Thread::get();}
01823
01853 class __EXPORT SysTime
01854 {
01855
private:
01856
static Mutex timeLock;
01857
01858
protected:
01859 inline static void lock(
void)
01860 {timeLock.enterMutex();}
01861
01862 inline static void unlock(
void)
01863 {timeLock.leaveMutex();}
01864
01865
public:
01866
static time_t getTime(time_t *tloc = NULL);
01867 static time_t time(time_t *tloc)
01868 {
return getTime(tloc); };
01869
01870
static int getTimeOfDay(
struct timeval *tp);
01871 static int gettimeofday(
struct timeval *tp,
struct timezone *)
01872 {
return getTimeOfDay(tp); };
01873
01874
static struct tm *getLocalTime(
const time_t *clock,
struct tm *result);
01875 static struct tm *locatime(
const time_t *clock,
struct tm *result)
01876 {
return getLocalTime(clock, result); };
01877
01878
static struct tm *getGMTTime(
const time_t *clock,
struct tm *result);
01879 static struct tm *gmtime(
const time_t *clock,
struct tm *result)
01880 {
return getGMTTime(clock, result);};
01881 };
01882
01883
#ifndef HAVE_LOCALTIME_R
01884
01885 inline struct tm *
localtime_r(
const time_t *t,
struct tm *b)
01886 {
return SysTime::getLocalTime(t, b);};
01887 inline char *
ctime_r(
const time_t *t,
char *buf)
01888 {
return ctime(t);};
01889 inline struct tm *
gmtime_r(
const time_t *t,
struct tm *b) \
01890 {
return SysTime::getGMTTime(t, b);};
01891 inline char *
asctime_r(
const struct tm *tm,
char *b) \
01892 {
return asctime(tm);};
01893
01894
#endif
01895
01896
#ifdef CCXX_NAMESPACES
01897
}
01898
#endif
01899
01900
#endif
01901