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 #ifndef _PTHREAD
00035 #define _PTHREAD
00036
00037 #ifdef P_USE_PRAGMA
00038 #pragma interface
00039 #endif
00040
00041 #ifdef Priority
00042 #undef Priority
00043 #endif
00044
00045 #include <ptlib/mutex.h>
00046
00047 class PSemaphore;
00048
00049 #define PThreadIdentifer PThreadIdentifier
00050
00051 typedef P_THREADIDENTIFIER PThreadIdentifier;
00052
00054
00055
00069 class PThread : public PObject
00070 {
00071 PCLASSINFO(PThread, PObject);
00072
00073 public:
00076
00077 enum Priority {
00078 LowestPriority,
00079
00080 LowPriority,
00081
00082 NormalPriority,
00083
00084 HighPriority,
00085
00086 HighestPriority,
00087
00088 NumPriorities
00089 };
00090
00092 enum AutoDeleteFlag {
00094 AutoDeleteThread,
00095
00097 NoAutoDeleteThread
00098 };
00099
00122 PThread(
00123 PINDEX,
00124 AutoDeleteFlag deletion = AutoDeleteThread,
00126 Priority priorityLevel = NormalPriority,
00127 const PString & threadName = PString::Empty()
00128 );
00129
00137 ~PThread();
00139
00146 void PrintOn(
00147 ostream & strm
00148 ) const;
00150
00158 virtual void Restart();
00159
00171 virtual void Terminate();
00172
00178 virtual PBoolean IsTerminated() const;
00179
00182 void WaitForTermination() const;
00183
00189 PBoolean WaitForTermination(
00190 const PTimeInterval & maxWait
00191 ) const;
00192
00205 virtual void Suspend(
00206 PBoolean susp = PTrue
00207 );
00208
00228 virtual void Resume();
00229
00237 virtual PBoolean IsSuspended() const;
00238
00240 static void Sleep(
00241 const PTimeInterval & delay
00242 );
00243
00247 virtual void SetPriority(
00248 Priority priorityLevel
00249 );
00250
00256 virtual Priority GetPriority() const;
00257
00261 virtual void SetAutoDelete(
00262 AutoDeleteFlag deletion = AutoDeleteThread
00263 );
00264
00268 void SetNoAutoDelete() { SetAutoDelete(NoAutoDeleteThread); }
00269
00275 virtual PString GetThreadName() const;
00276
00282 virtual void SetThreadName(
00283 const PString & name
00284 );
00286
00294 virtual PThreadIdentifier GetThreadId() const;
00295 static PThreadIdentifier GetCurrentThreadId();
00296
00304 virtual void Main() = 0;
00305
00315 static PThread * Current();
00316
00323 static void Yield();
00324
00329 static PThread * Create(
00330 const PNotifier & notifier,
00331 INT parameter = 0,
00332 AutoDeleteFlag deletion = AutoDeleteThread,
00334 Priority priorityLevel = NormalPriority,
00335 const PString & threadName = PString::Empty(),
00336 PINDEX stackSize = 65536
00337 );
00338 static PThread * Create(
00339 const PNotifier & notifier,
00340 const PString & threadName
00341 ) { return Create(notifier, 0, NoAutoDeleteThread, NormalPriority, threadName); }
00343
00344 protected:
00345 void InitialiseProcessThread();
00346
00347
00348
00349
00350 private:
00351 PThread();
00352
00353
00354 friend class PProcess;
00355
00356
00357 PThread(const PThread &) : PObject () { }
00358
00359
00360 PThread & operator=(const PThread &) { return *this; }
00361
00362
00363 PBoolean autoDelete;
00364
00365
00366
00367 PString threadName;
00368 PMutex threadNameMutex;
00369
00370 #if PTRACING
00371 public:
00372 struct TraceInfo {
00373 TraceInfo()
00374 { traceBlockIndentLevel = 0; }
00375
00376 PStack<PStringStream> traceStreams;
00377 unsigned traceLevel;
00378 unsigned traceBlockIndentLevel;
00379 };
00380
00381 #ifndef P_HAS_THREADLOCAL_STORAGE
00382 private:
00383 friend class PTrace;
00384 TraceInfo traceInfo;
00385 #endif // P_HAS_THREADLOCAL_STORAGE
00386 #endif // PTRACING
00387
00388
00389 #ifdef _WIN32
00390 #include "msos/ptlib/thread.h"
00391 #else
00392 #include "unix/ptlib/thread.h"
00393 #endif
00394 };
00395
00396
00397 #if defined(_WIN32) && !defined(_WIN32_WCE)
00398 #define PTHREAD_ID_FMT ":%u"
00399 #else
00400 #define PTHREAD_ID_FMT ":0x%x"
00401 #endif
00402
00403 #ifdef _MSC_VER
00404 #pragma warning(disable:4355)
00405 #endif
00406
00411
00412
00413
00414
00415
00416
00417
00418
00419
00420
00421
00422
00423 class PThreadMain : public PThread
00424 {
00425 PCLASSINFO(PThreadMain, PThread);
00426 public:
00427 typedef void (*FnType)();
00428 PThreadMain(FnType _fn, PBoolean _autoDelete = PFalse)
00429 : PThread(10000, _autoDelete ? PThread::AutoDeleteThread : PThread::NoAutoDeleteThread), fn(_fn)
00430 { PThread::Resume(); }
00431 PThreadMain(const char * _file, int _line, FnType _fn, PBoolean _autoDelete = PFalse)
00432 : PThread(10000, _autoDelete ? PThread::AutoDeleteThread : PThread::NoAutoDeleteThread, NormalPriority,
00433 psprintf("%s:%08x-%s:%i", GetClass(), (void *)this, _file, _line)), fn(_fn)
00434 { PThread::Resume(); }
00435 virtual void Main()
00436 { (*fn)(); }
00437 FnType fn;
00438 };
00439
00440
00441
00442
00443
00444
00445
00446
00447
00448
00449
00450
00451
00452 template<typename Arg1Type>
00453 class PThread1Arg : public PThread
00454 {
00455 PCLASSINFO(PThread1Arg, PThread);
00456 public:
00457 typedef void (*FnType)(Arg1Type arg1);
00458 PThread1Arg(Arg1Type _arg1, FnType _fn, PBoolean _autoDelete = PFalse)
00459 : PThread(10000, _autoDelete ? PThread::AutoDeleteThread : PThread::NoAutoDeleteThread), fn(_fn),
00460 arg1(_arg1)
00461 { PThread::Resume(); }
00462 PThread1Arg(const char * _file, int _line, Arg1Type _arg1, FnType _fn, PBoolean _autoDelete = PFalse)
00463 : PThread(10000, _autoDelete ? PThread::AutoDeleteThread : PThread::NoAutoDeleteThread, NormalPriority,
00464 psprintf("%s:%08x-%s:%i", GetClass(), (void *)this, _file, _line)), fn(_fn),
00465 arg1(_arg1)
00466 { PThread::Resume(); }
00467 virtual void Main()
00468 { (*fn)(arg1); }
00469 FnType fn;
00470 Arg1Type arg1;
00471 };
00472
00473
00474
00475
00476
00477
00478
00479
00480
00481
00482
00483
00484
00485
00486 template<typename Arg1Type, typename Arg2Type>
00487 class PThread2Arg : public PThread
00488 {
00489 PCLASSINFO(PThread2Arg, PThread);
00490 public:
00491 typedef void (*FnType)(Arg1Type arg1, Arg2Type arg2);
00492 PThread2Arg(Arg1Type _arg1, Arg2Type _arg2, FnType _fn, PBoolean _autoDelete = PFalse)
00493 : PThread(10000, _autoDelete ? PThread::AutoDeleteThread : PThread::NoAutoDeleteThread), fn(_fn),
00494 arg1(_arg1), arg2(_arg2)
00495 { PThread::Resume(); }
00496 PThread2Arg(const char * _file, int _line, Arg1Type _arg1, Arg2Type _arg2, FnType _fn, PBoolean _autoDelete = PFalse)
00497 : PThread(10000, _autoDelete ? PThread::AutoDeleteThread : PThread::NoAutoDeleteThread, NormalPriority,
00498 psprintf("%s:%08x-%s:%i", GetClass(), (void *)this, _file, _line)), fn(_fn),
00499 arg1(_arg1), arg2(_arg2)
00500 { PThread::Resume(); }
00501 virtual void Main()
00502 { (*fn)(arg1, arg2); }
00503 FnType fn;
00504 Arg1Type arg1;
00505 Arg2Type arg2;
00506 };
00507
00508
00509
00510
00511
00512
00513
00514
00515
00516
00517
00518
00519
00520 template<typename Arg1Type, typename Arg2Type, typename Arg3Type>
00521 class PThread3Arg : public PThread
00522 {
00523 PCLASSINFO(PThread3Arg, PThread);
00524 public:
00525 typedef void (*FnType)(Arg1Type arg1, Arg2Type arg2, Arg3Type arg3);
00526 PThread3Arg(Arg1Type _arg1, Arg2Type _arg2, Arg3Type _arg3, FnType _fn, PBoolean _autoDelete = PFalse)
00527 : PThread(10000, _autoDelete ? PThread::AutoDeleteThread : PThread::NoAutoDeleteThread), fn(_fn),
00528 arg1(_arg1), arg2(_arg2), arg3(_arg3)
00529 { PThread::Resume(); }
00530 PThread3Arg(const char * _file, int _line, Arg1Type _arg1, Arg2Type _arg2, Arg3Type _arg3, FnType _fn, PBoolean _autoDelete = PFalse)
00531 : PThread(10000, _autoDelete ? PThread::AutoDeleteThread : PThread::NoAutoDeleteThread, NormalPriority,
00532 psprintf("%s:%08x-%s:%i", GetClass(), (void *)this, _file, _line)), fn(_fn),
00533 arg1(_arg1), arg2(_arg2), arg3(_arg3)
00534 { PThread::Resume(); }
00535 virtual void Main()
00536 { (*fn)(arg1, arg2, arg3); }
00537 FnType fn;
00538 Arg1Type arg1;
00539 Arg2Type arg2;
00540 Arg2Type arg3;
00541 };
00542
00543
00544
00545
00546
00547
00548
00549
00550
00551
00552
00553
00554
00555
00556
00557
00558
00559 template <typename ObjType>
00560 class PThreadObj : public PThread
00561 {
00562 public:
00563 PCLASSINFO(PThreadObj, PThread);
00564 public:
00565 typedef void (ObjType::*ObjTypeFn)();
00566 PThreadObj(ObjType & _obj, ObjTypeFn _fn, PBoolean _autoDelete = PFalse)
00567 : PThread(10000, _autoDelete ? PThread::AutoDeleteThread : PThread::NoAutoDeleteThread),
00568 obj(_obj), fn(_fn)
00569 { PThread::Resume(); }
00570 PThreadObj(const char * _file, int _line, ObjType & _obj, ObjTypeFn _fn, PBoolean _autoDelete = PFalse)
00571 : PThread(10000, _autoDelete ? PThread::AutoDeleteThread : PThread::NoAutoDeleteThread, NormalPriority,
00572 psprintf("%s:%08x-%s:%i", GetClass(), (void *)this, _file, _line)),
00573 obj(_obj), fn(_fn)
00574 { PThread::Resume(); }
00575 void Main()
00576 { (obj.*fn)(); }
00577
00578 protected:
00579 ObjType & obj;
00580 ObjTypeFn fn;
00581 };
00582
00583
00584
00585
00586
00587
00588
00589
00590
00591
00592
00593
00594
00595
00596
00597
00598
00599
00600 template <class ObjType, typename Arg1Type>
00601 class PThreadObj1Arg : public PThread
00602 {
00603 PCLASSINFO(PThreadObj1Arg, PThread);
00604 public:
00605 typedef void (ObjType::*ObjTypeFn)(Arg1Type);
00606 PThreadObj1Arg(ObjType & _obj, Arg1Type _arg1, ObjTypeFn _fn, PBoolean _autoDelete = PFalse)
00607 : PThread(10000, _autoDelete ? PThread::AutoDeleteThread : PThread::NoAutoDeleteThread),
00608 obj(_obj), fn(_fn), arg1(_arg1)
00609 { PThread::Resume(); }
00610 PThreadObj1Arg(const char * _file, int _line, ObjType & _obj, Arg1Type _arg1, ObjTypeFn _fn, PBoolean _autoDelete = PFalse)
00611 : PThread(10000, _autoDelete ? PThread::AutoDeleteThread : PThread::NoAutoDeleteThread, NormalPriority,
00612 psprintf("%s:%08x-%s:%i", GetClass(), (void *)this, _file, _line)),
00613 obj(_obj), fn(_fn), arg1(_arg1)
00614 { PThread::Resume(); }
00615 void Main()
00616 { (obj.*fn)(arg1); }
00617
00618 protected:
00619 ObjType & obj;
00620 ObjTypeFn fn;
00621 Arg1Type arg1;
00622 };
00623
00624 template <class ObjType, typename Arg1Type, typename Arg2Type>
00625 class PThreadObj2Arg : public PThread
00626 {
00627 PCLASSINFO(PThreadObj2Arg, PThread);
00628 public:
00629 typedef void (ObjType::*ObjTypeFn)(Arg1Type, Arg2Type);
00630 PThreadObj2Arg(ObjType & _obj, Arg1Type _arg1, Arg2Type _arg2, ObjTypeFn _fn, PBoolean _autoDelete = PFalse)
00631 : PThread(10000, _autoDelete ? PThread::AutoDeleteThread : PThread::NoAutoDeleteThread),
00632 obj(_obj), fn(_fn), arg1(_arg1), arg2(_arg2)
00633 { PThread::Resume(); }
00634 PThreadObj2Arg(const char * _file, int _line, ObjType & _obj, Arg1Type _arg1, Arg2Type _arg2, ObjTypeFn _fn, PBoolean _autoDelete = PFalse)
00635 : PThread(10000, _autoDelete ? PThread::AutoDeleteThread : PThread::NoAutoDeleteThread, NormalPriority,
00636 psprintf("%s:%08x-%s:%i", GetClass(), (void *)this, _file, _line)),
00637 obj(_obj), fn(_fn), arg1(_arg1), arg2(_arg2)
00638 { PThread::Resume(); }
00639 void Main()
00640 { (obj.*fn)(arg1, arg2); }
00641
00642 protected:
00643 ObjType & obj;
00644 ObjTypeFn fn;
00645 Arg1Type arg1;
00646 Arg1Type arg2;
00647 };
00648
00649
00651
00652
00653
00654
00655 #ifdef _WIN32
00656
00657 #define P_HAS_THREADLOCAL_STORAGE 1
00658
00659 template <class Storage_T>
00660 class PThreadLocalStorage
00661 {
00662 public:
00663 typedef DWORD Key_T;
00664 typedef Storage_T value_type;
00665
00666 PThreadLocalStorage()
00667 { key = TlsAlloc(); }
00668
00669 ~PThreadLocalStorage()
00670 { TlsFree(key); }
00671
00672 Key_T GetKey() const
00673 { return key; }
00674
00675 value_type * Get()
00676 { return (value_type *) TlsGetValue(key); }
00677
00678 void Set(value_type * v)
00679 { TlsSetValue(key, (LPVOID)v); }
00680
00681 protected:
00682 DWORD key;
00683 };
00684
00685 #elif defined(P_PTHREADS)
00686
00687 #include <pthread.h>
00688
00689 #define P_HAS_THREADLOCAL_STORAGE 1
00690
00691 template <class Storage_T>
00692 class PThreadLocalStorage
00693 {
00694 public:
00695 typedef pthread_key_t Key_T;
00696 typedef Storage_T value_type;
00697
00698 PThreadLocalStorage()
00699 { pthread_key_create(&key, NULL); }
00700
00701 ~PThreadLocalStorage()
00702 { pthread_key_delete(key); }
00703
00704 Key_T GetKey() const
00705 { return key; }
00706
00707 value_type * Get()
00708 { return (value_type *)pthread_getspecific(key); }
00709
00710 void Set(value_type * v)
00711 { pthread_setspecific(key, v); }
00712
00713 private:
00714 Key_T key;
00715 };
00716
00717 #else
00718
00719 #undef P_HAS_THREADLOCAL_STORAGE 1
00720 #warning("Thread local storage not supported");
00721
00722 #endif
00723
00724
00725 #ifdef _MSC_VER
00726 #pragma warning(default:4355)
00727 #endif
00728
00729 #endif // _PTHREAD
00730
00731