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 PTLIB_THREAD_H
00035 #define PTLIB_THREAD_H
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 = true
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
00298 struct Times
00299 {
00300 PTimeInterval m_real;
00301 PTimeInterval m_kernel;
00302 PTimeInterval m_user;
00303 friend ostream & operator<<(ostream & strm, const Times & times);
00304 };
00305
00308 bool GetTimes(
00309 Times & times
00310 );
00311
00319 virtual void Main() = 0;
00320
00330 static PThread * Current();
00331
00338 static void Yield();
00339
00344 static PThread * Create(
00345 const PNotifier & notifier,
00346 INT parameter = 0,
00347 AutoDeleteFlag deletion = AutoDeleteThread,
00349 Priority priorityLevel = NormalPriority,
00350 const PString & threadName = PString::Empty(),
00351 PINDEX stackSize = 65536
00352 );
00353 static PThread * Create(
00354 const PNotifier & notifier,
00355 const PString & threadName
00356 ) { return Create(notifier, 0, NoAutoDeleteThread, NormalPriority, threadName); }
00358
00359 bool IsAutoDelete() const { return autoDelete; }
00360
00361 private:
00362 PThread();
00363
00364
00365 friend class PProcess;
00366 friend class PExternalThread;
00367 friend class PHouseKeepingThread;
00368
00369
00370 PThread(const PThread &) : PObject () { }
00371
00372
00373 PThread & operator=(const PThread &) { return *this; }
00374
00375
00376 PBoolean autoDelete;
00377
00378
00379
00380 PString threadName;
00381 PMutex threadNameMutex;
00382
00383 #if PTRACING
00384 public:
00385 struct TraceInfo {
00386 TraceInfo()
00387 { traceBlockIndentLevel = 0; }
00388
00389 PStack<PStringStream> traceStreams;
00390 unsigned traceLevel;
00391 unsigned traceBlockIndentLevel;
00392 };
00393
00394 #ifndef P_HAS_THREADLOCAL_STORAGE
00395 private:
00396 friend class PTrace;
00397 TraceInfo traceInfo;
00398 #endif // P_HAS_THREADLOCAL_STORAGE
00399 #endif // PTRACING
00400
00401
00402 #ifdef _WIN32
00403 #include "msos/ptlib/thread.h"
00404 #else
00405 #include "unix/ptlib/thread.h"
00406 #endif
00407 };
00408
00409
00410 #if defined(_WIN32) && !defined(_WIN32_WCE)
00411 #define PTHREAD_ID_FMT ":%u"
00412 #else
00413 #define PTHREAD_ID_FMT ":0x%x"
00414 #endif
00415
00416 #ifdef _MSC_VER
00417 #pragma warning(disable:4355)
00418 #endif
00419
00424
00425
00426
00427
00428
00429
00430
00431
00432
00433
00434
00435
00436 class PThreadMain : public PThread
00437 {
00438 PCLASSINFO(PThreadMain, PThread);
00439 public:
00440 typedef void (*FnType)();
00441 PThreadMain(FnType function, bool autoDel = false)
00442 : PThread(10000, autoDel ? PThread::AutoDeleteThread : PThread::NoAutoDeleteThread)
00443 , m_function(function)
00444 { PThread::Resume(); }
00445 PThreadMain(const char * file, int line, FnType function, bool autoDel = false)
00446 : PThread(10000, autoDel ? PThread::AutoDeleteThread : PThread::NoAutoDeleteThread, NormalPriority,
00447 psprintf("%s:%08x-%s:%i", GetClass(), (void *)this, file, line))
00448 , m_function(function)
00449 { PThread::Resume(); }
00450 virtual void Main()
00451 { (*m_function)(); }
00452
00453 protected:
00454 FnType m_function;
00455 };
00456
00457
00458
00459
00460
00461
00462
00463
00464
00465
00466
00467
00468
00469 template<typename Arg1Type>
00470 class PThread1Arg : public PThread
00471 {
00472 PCLASSINFO(PThread1Arg, PThread);
00473 public:
00474 typedef void (*FnType)(Arg1Type arg1);
00475
00476 PThread1Arg(Arg1Type arg1, FnType function, bool autoDel = false)
00477 : PThread(10000, autoDel ? PThread::AutoDeleteThread : PThread::NoAutoDeleteThread)
00478 , m_function(function)
00479 , m_arg1(arg1)
00480 { PThread::Resume(); }
00481 PThread1Arg(const char * file, int line, Arg1Type arg1, FnType function, bool autoDel = false)
00482 : PThread(10000, autoDel ? PThread::AutoDeleteThread : PThread::NoAutoDeleteThread, NormalPriority,
00483 psprintf("%s:%08x-%s:%i", GetClass(), (void *)this, file, line))
00484 , m_function(function)
00485 , m_arg1(arg1)
00486 { PThread::Resume(); }
00487 virtual void Main()
00488 { (*m_function)(m_arg1); }
00489
00490 protected:
00491 FnType m_function;
00492 Arg1Type m_arg1;
00493 };
00494
00495
00496
00497
00498
00499
00500
00501
00502
00503
00504
00505
00506
00507
00508 template<typename Arg1Type, typename Arg2Type>
00509 class PThread2Arg : public PThread
00510 {
00511 PCLASSINFO(PThread2Arg, PThread);
00512 public:
00513 typedef void (*FnType)(Arg1Type arg1, Arg2Type arg2);
00514 PThread2Arg(Arg1Type arg1, Arg2Type arg2, FnType function, bool autoDel = false)
00515 : PThread(10000, autoDel ? PThread::AutoDeleteThread : PThread::NoAutoDeleteThread)
00516 , m_function(function)
00517 , m_arg1(arg1)
00518 , m_arg2(arg2)
00519 { PThread::Resume(); }
00520 PThread2Arg(const char * file, int line, Arg1Type arg1, Arg2Type arg2, FnType function, bool autoDel = false)
00521 : PThread(10000, autoDel ? PThread::AutoDeleteThread : PThread::NoAutoDeleteThread, NormalPriority,
00522 psprintf("%s:%08x-%s:%i", GetClass(), (void *)this, file, line))
00523 , m_function(function)
00524 , m_arg1(arg1)
00525 , m_arg2(arg2)
00526 { PThread::Resume(); }
00527 virtual void Main()
00528 { (*m_function)(m_arg1, m_arg2); }
00529
00530 protected:
00531 FnType m_function;
00532 Arg1Type m_arg1;
00533 Arg2Type m_arg2;
00534 };
00535
00536
00537
00538
00539
00540
00541
00542
00543
00544
00545
00546
00547
00548 template<typename Arg1Type, typename Arg2Type, typename Arg3Type>
00549 class PThread3Arg : public PThread
00550 {
00551 PCLASSINFO(PThread3Arg, PThread);
00552 public:
00553 typedef void (*FnType)(Arg1Type arg1, Arg2Type arg2, Arg3Type arg3);
00554 PThread3Arg(Arg1Type arg1, Arg2Type arg2, Arg3Type arg3, FnType function, bool autoDel = false)
00555 : PThread(10000, autoDel ? PThread::AutoDeleteThread : PThread::NoAutoDeleteThread)
00556 , m_function(function)
00557 , m_arg1(arg1)
00558 , m_arg2(arg2)
00559 , m_arg3(arg3)
00560 { PThread::Resume(); }
00561 PThread3Arg(const char * file, int line, Arg1Type arg1, Arg2Type arg2, Arg3Type arg3, FnType function, bool autoDel = false)
00562 : PThread(10000, autoDel ? PThread::AutoDeleteThread : PThread::NoAutoDeleteThread, NormalPriority,
00563 psprintf("%s:%08x-%s:%i", GetClass(), (void *)this, file, line))
00564 , m_function(function)
00565 , m_arg1(arg1)
00566 , m_arg2(arg2)
00567 , m_arg3(arg3)
00568 { PThread::Resume(); }
00569 virtual void Main()
00570 { (*m_function)(m_arg1, m_arg2, m_arg3); }
00571
00572 protected:
00573 FnType m_function;
00574 Arg1Type m_arg1;
00575 Arg2Type m_arg2;
00576 Arg2Type m_arg3;
00577 };
00578
00579
00580
00581
00582
00583
00584
00585
00586
00587
00588
00589
00590
00591
00592
00593
00594
00595 template <typename ObjType>
00596 class PThreadObj : public PThread
00597 {
00598 PCLASSINFO(PThreadObj, PThread);
00599 public:
00600 typedef void (ObjType::*ObjTypeFn)();
00601
00602 PThreadObj(
00603 ObjType & obj,
00604 ObjTypeFn function,
00605 bool autoDel = false,
00606 const char * name = NULL,
00607 PThread::Priority priority = PThread::NormalPriority
00608 ) : PThread(10000,
00609 autoDel ? PThread::AutoDeleteThread : PThread::NoAutoDeleteThread,
00610 priority,
00611 name)
00612 , m_object(obj)
00613 , m_function(function)
00614 {
00615 PThread::Resume();
00616 }
00617
00618 void Main()
00619 {
00620 (m_object.*m_function)();
00621 }
00622
00623 protected:
00624 ObjType & m_object;
00625 ObjTypeFn m_function;
00626 };
00627
00628
00629
00630
00631
00632
00633
00634
00635
00636
00637
00638
00639
00640
00641
00642
00643
00644
00645 template <class ObjType, typename Arg1Type>
00646 class PThreadObj1Arg : public PThread
00647 {
00648 PCLASSINFO(PThreadObj1Arg, PThread);
00649 public:
00650 typedef void (ObjType::*ObjTypeFn)(Arg1Type);
00651
00652 PThreadObj1Arg(
00653 ObjType & obj,
00654 Arg1Type arg1,
00655 ObjTypeFn function,
00656 bool autoDel = false,
00657 const char * name = NULL,
00658 PThread::Priority priority = PThread::NormalPriority
00659 ) : PThread(10000,
00660 autoDel ? PThread::AutoDeleteThread : PThread::NoAutoDeleteThread,
00661 priority,
00662 name)
00663 , m_object(obj)
00664 , m_function(function)
00665 , m_arg1(arg1)
00666 {
00667 PThread::Resume();
00668 }
00669
00670 void Main()
00671 {
00672 (m_object.*m_function)(m_arg1);
00673 }
00674
00675 protected:
00676 ObjType & m_object;
00677 ObjTypeFn m_function;
00678 Arg1Type m_arg1;
00679 };
00680
00681 template <class ObjType, typename Arg1Type, typename Arg2Type>
00682 class PThreadObj2Arg : public PThread
00683 {
00684 PCLASSINFO(PThreadObj2Arg, PThread);
00685 public:
00686 typedef void (ObjType::*ObjTypeFn)(Arg1Type, Arg2Type);
00687
00688 PThreadObj2Arg(
00689 ObjType & obj,
00690 Arg1Type arg1,
00691 Arg2Type arg2,
00692 ObjTypeFn function,
00693 bool autoDel = false,
00694 const char * name = NULL,
00695 PThread::Priority priority = PThread::NormalPriority
00696 ) : PThread(10000,
00697 autoDel ? PThread::AutoDeleteThread : PThread::NoAutoDeleteThread,
00698 priority,
00699 name)
00700 , m_object(obj)
00701 , m_function(function)
00702 , m_arg1(arg1)
00703 , m_arg2(arg2)
00704 {
00705 PThread::Resume();
00706 }
00707
00708 void Main()
00709 {
00710 (m_object.*m_function)(m_arg1, m_arg2);
00711 }
00712
00713 protected:
00714 ObjType & m_object;
00715 ObjTypeFn m_function;
00716 Arg1Type m_arg1;
00717 Arg2Type m_arg2;
00718 };
00719
00720
00722
00723
00724
00725
00726 #ifdef _WIN32
00727
00728 #define P_HAS_THREADLOCAL_STORAGE 1
00729
00730 template <class Storage_T>
00731 class PThreadLocalStorage
00732 {
00733 public:
00734 typedef DWORD Key_T;
00735 typedef Storage_T value_type;
00736
00737 PThreadLocalStorage()
00738 { key = TlsAlloc(); }
00739
00740 ~PThreadLocalStorage()
00741 { TlsFree(key); }
00742
00743 Key_T GetKey() const
00744 { return key; }
00745
00746 value_type * Get()
00747 { return (value_type *) TlsGetValue(key); }
00748
00749 void Set(value_type * v)
00750 { TlsSetValue(key, (LPVOID)v); }
00751
00752 protected:
00753 DWORD key;
00754 };
00755
00756 #elif defined(P_PTHREADS)
00757
00758 #include <pthread.h>
00759
00760 #define P_HAS_THREADLOCAL_STORAGE 1
00761
00762 template <class Storage_T>
00763 class PThreadLocalStorage
00764 {
00765 public:
00766 typedef pthread_key_t Key_T;
00767 typedef Storage_T value_type;
00768
00769 PThreadLocalStorage()
00770 { pthread_key_create(&key, NULL); }
00771
00772 ~PThreadLocalStorage()
00773 { pthread_key_delete(key); }
00774
00775 Key_T GetKey() const
00776 { return key; }
00777
00778 value_type * Get()
00779 { return (value_type *)pthread_getspecific(key); }
00780
00781 void Set(value_type * v)
00782 { pthread_setspecific(key, v); }
00783
00784 private:
00785 Key_T key;
00786 };
00787
00788 #else
00789
00790 #undef P_HAS_THREADLOCAL_STORAGE 1
00791 #warning("Thread local storage not supported");
00792
00793 #endif
00794
00795
00796 #ifdef _MSC_VER
00797 #pragma warning(default:4355)
00798 #endif
00799
00800 #endif // PTLIB_THREAD_H
00801
00802