thread.h

Go to the documentation of this file.
00001 /*
00002  * thread.h
00003  *
00004  * Executable thread encapsulation class (pre-emptive if OS allows).
00005  *
00006  * Portable Tools Library
00007  *
00008  * Copyright (c) 1993-1998 Equivalence Pty. Ltd.
00009  *
00010  * The contents of this file are subject to the Mozilla Public License
00011  * Version 1.0 (the "License"); you may not use this file except in
00012  * compliance with the License. You may obtain a copy of the License at
00013  * http://www.mozilla.org/MPL/
00014  *
00015  * Software distributed under the License is distributed on an "AS IS"
00016  * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
00017  * the License for the specific language governing rights and limitations
00018  * under the License.
00019  *
00020  * The Original Code is Portable Windows Library.
00021  *
00022  * The Initial Developer of the Original Code is Equivalence Pty. Ltd.
00023  *
00024  * Portions are Copyright (C) 1993 Free Software Foundation, Inc.
00025  * All Rights Reserved.
00026  *
00027  * Contributor(s): ______________________________________.
00028  *
00029  * $Revision: 21791 $
00030  * $Author: rjongbloed $
00031  * $Date: 2008-12-12 00:07:11 -0600 (Fri, 12 Dec 2008) $
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 // PThread
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     bool IsAutoDelete() const { return autoDelete; }
00345 
00346   private:
00347     PThread();
00348     // Create a new thread instance as part of a #PProcess class.
00349 
00350     friend class PProcess;
00351     friend class PExternalThread;
00352     friend class PHouseKeepingThread;
00353     // So a PProcess can get at PThread() constructor but nothing else.
00354 
00355     PThread(const PThread &) : PObject () { }
00356     // Empty constructor to prevent copying of thread instances.
00357 
00358     PThread & operator=(const PThread &) { return *this; }
00359     // Empty assignment operator to prevent copying of thread instances.
00360 
00361     PBoolean autoDelete;
00362     // Automatically delete the thread on completion.
00363 
00364     // Give the thread a name for debugging purposes.
00365     PString threadName;
00366     PMutex threadNameMutex;
00367 
00368 #if PTRACING
00369   public:
00370     struct TraceInfo {
00371       TraceInfo()
00372       { traceBlockIndentLevel = 0; }
00373 
00374       PStack<PStringStream> traceStreams;
00375       unsigned traceLevel;
00376       unsigned traceBlockIndentLevel;
00377     };
00378 
00379 #ifndef P_HAS_THREADLOCAL_STORAGE
00380   private:
00381     friend class PTrace;
00382     TraceInfo traceInfo;
00383 #endif // P_HAS_THREADLOCAL_STORAGE
00384 #endif // PTRACING
00385 
00386 // Include platform dependent part of class
00387 #ifdef _WIN32
00388 #include "msos/ptlib/thread.h"
00389 #else
00390 #include "unix/ptlib/thread.h"
00391 #endif
00392 };
00393 
00394 // Include definition of platform dependent thread ID format
00395 #if defined(_WIN32) && !defined(_WIN32_WCE)
00396   #define PTHREAD_ID_FMT ":%u"
00397 #else
00398   #define PTHREAD_ID_FMT ":0x%x"
00399 #endif
00400 
00401 #ifdef _MSC_VER
00402 #pragma warning(disable:4355)
00403 #endif
00404 
00409 /*
00410    This class automates calling a global function with no arguments within it's own thread.
00411    It is used as follows:
00412 
00413    void GlobalFunction()
00414    {
00415    }
00416 
00417    ...
00418    PString arg;
00419    new PThreadMain(&GlobalFunction)
00420  */
00421 class PThreadMain : public PThread
00422 {
00423   PCLASSINFO(PThreadMain, PThread);
00424   public:
00425     typedef void (*FnType)(); 
00426     PThreadMain(FnType function, bool autoDelete = false)
00427       : PThread(10000, autoDelete ? PThread::AutoDeleteThread : PThread::NoAutoDeleteThread)
00428       , m_function(function)
00429       { PThread::Resume(); }
00430     PThreadMain(const char * file, int line, FnType function, bool autoDelete = false)
00431       : PThread(10000, autoDelete ? PThread::AutoDeleteThread : PThread::NoAutoDeleteThread,  NormalPriority,
00432                 psprintf("%s:%08x-%s:%i", GetClass(), (void *)this, file, line))
00433       , m_function(function)
00434       { PThread::Resume(); }
00435     virtual void Main()
00436       { (*m_function)(); }
00437 
00438   protected:
00439     FnType m_function;
00440 };
00441 
00442 /*
00443    This template automates calling a global function with one argument within it's own thread.
00444    It is used as follows:
00445 
00446    void GlobalFunction(PString arg)
00447    {
00448    }
00449 
00450    ...
00451    PString arg;
00452    new PThread1Arg<PString>(arg, &GlobalFunction)
00453  */
00454 template<typename Arg1Type>
00455 class PThread1Arg : public PThread
00456 {
00457   PCLASSINFO(PThread1Arg, PThread);
00458   public:
00459     typedef void (*FnType)(Arg1Type arg1);
00460 
00461     PThread1Arg(Arg1Type arg1, FnType function, bool autoDelete = false)
00462       : PThread(10000, autoDelete ? PThread::AutoDeleteThread : PThread::NoAutoDeleteThread)
00463       , m_function(function)
00464       , m_arg1(arg1)
00465     { PThread::Resume(); }
00466     PThread1Arg(const char * file, int line, Arg1Type arg1, FnType function, bool autoDelete = false)
00467       : PThread(10000, autoDelete ? PThread::AutoDeleteThread : PThread::NoAutoDeleteThread, NormalPriority,
00468                 psprintf("%s:%08x-%s:%i", GetClass(), (void *)this, file, line))
00469       , m_function(function)
00470       , m_arg1(arg1)
00471       { PThread::Resume(); }
00472     virtual void Main()
00473       { (*m_function)(m_arg1); }
00474 
00475   protected:
00476     FnType   m_function;
00477     Arg1Type m_arg1;
00478 };
00479 
00480 
00481 /*
00482    This template automates calling a global function with two arguments within it's own thread.
00483    It is used as follows:
00484 
00485    void GlobalFunction(PString arg1, int arg2)
00486    {
00487    }
00488 
00489    ...
00490    PString arg;
00491    new PThread2Arg<PString, int>(arg1, arg2, &GlobalFunction)
00492  */
00493 template<typename Arg1Type, typename Arg2Type>
00494 class PThread2Arg : public PThread
00495 {
00496   PCLASSINFO(PThread2Arg, PThread);
00497   public:
00498     typedef void (*FnType)(Arg1Type arg1, Arg2Type arg2); 
00499     PThread2Arg(Arg1Type arg1, Arg2Type arg2, FnType function, bool autoDelete = false)
00500       : PThread(10000, autoDelete ? PThread::AutoDeleteThread : PThread::NoAutoDeleteThread)
00501       , m_function(function)
00502       , m_arg1(arg1)
00503       , m_arg2(arg2)
00504       { PThread::Resume(); }
00505     PThread2Arg(const char * file, int line, Arg1Type arg1, Arg2Type arg2, FnType function, bool autoDelete = false)
00506       : PThread(10000, autoDelete ? PThread::AutoDeleteThread : PThread::NoAutoDeleteThread, NormalPriority,
00507                 psprintf("%s:%08x-%s:%i", GetClass(), (void *)this, file, line))
00508       , m_function(function)
00509       , m_arg1(arg1)
00510       , m_arg2(arg2)
00511       { PThread::Resume(); }
00512     virtual void Main()
00513       { (*m_function)(m_arg1, m_arg2); }
00514 
00515   protected:
00516     FnType   m_function;
00517     Arg1Type m_arg1;
00518     Arg2Type m_arg2;
00519 };
00520 
00521 /*
00522    This template automates calling a global function with three arguments within it's own thread.
00523    It is used as follows:
00524 
00525    void GlobalFunction(PString arg1, int arg2, int arg3)
00526    {
00527    }
00528 
00529    ...
00530    PString arg;
00531    new PThread3Arg<PString, int, int>(arg1, arg2, arg3, &GlobalFunction)
00532  */
00533 template<typename Arg1Type, typename Arg2Type, typename Arg3Type>
00534 class PThread3Arg : public PThread
00535 {
00536   PCLASSINFO(PThread3Arg, PThread);
00537   public:
00538     typedef void (*FnType)(Arg1Type arg1, Arg2Type arg2, Arg3Type arg3); 
00539     PThread3Arg(Arg1Type arg1, Arg2Type arg2, Arg3Type arg3, FnType function, bool autoDelete = false)
00540       : PThread(10000, autoDelete ? PThread::AutoDeleteThread : PThread::NoAutoDeleteThread)
00541       , m_function(function)
00542       , m_arg1(arg1)
00543       , m_arg2(arg2)
00544       , m_arg3(arg3)
00545       { PThread::Resume(); }
00546     PThread3Arg(const char * file, int line, Arg1Type arg1, Arg2Type arg2, Arg3Type arg3, FnType function, bool autoDelete = false)
00547       : PThread(10000, autoDelete ? PThread::AutoDeleteThread : PThread::NoAutoDeleteThread, NormalPriority,
00548                 psprintf("%s:%08x-%s:%i", GetClass(), (void *)this, file, line))
00549       , m_function(function)
00550       , m_arg1(arg1)
00551       , m_arg2(arg2)
00552       , m_arg3(arg3)
00553       { PThread::Resume(); }
00554     virtual void Main()
00555       { (*m_function)(m_arg1, m_arg2, m_arg3); }
00556 
00557   protected:
00558     FnType   m_function;
00559     Arg1Type m_arg1;
00560     Arg2Type m_arg2;
00561     Arg2Type m_arg3;
00562 };
00563 
00564 /*
00565    This template automates calling a member function with no arguments within it's own thread.
00566    It is used as follows:
00567 
00568    class Example {
00569      public:
00570       void Function()
00571       {
00572       }
00573    };
00574 
00575    ...
00576    Example ex;
00577    new PThreadObj<Example>(ex, &Example::Function)
00578  */
00579 
00580 template <typename ObjType>
00581 class PThreadObj : public PThread
00582 {
00583   public:
00584   PCLASSINFO(PThreadObj, PThread);
00585   public:
00586     typedef void (ObjType::*ObjTypeFn)(); 
00587     PThreadObj(ObjType & obj, ObjTypeFn function, bool autoDelete = false)
00588       : PThread(10000, autoDelete ? PThread::AutoDeleteThread : PThread::NoAutoDeleteThread)
00589       , m_object(obj)
00590       , m_function(function)
00591       { PThread::Resume(); }
00592     PThreadObj(const char * file, int line, ObjType & obj, ObjTypeFn function, bool autoDelete = false)
00593       : PThread(10000, autoDelete ? PThread::AutoDeleteThread : PThread::NoAutoDeleteThread, NormalPriority,
00594                 psprintf("%s:%08x-%s:%i", GetClass(), (void *)this, file, line))
00595       , m_object(obj)
00596       , m_function(function)
00597       { PThread::Resume(); }
00598     void Main()
00599       { (m_object.*m_function)(); }
00600 
00601   protected:
00602     ObjType & m_object;
00603     ObjTypeFn m_function;
00604 };
00605 
00606 
00607 /*
00608    This template automates calling a member function with one argument within it's own thread.
00609    It is used as follows:
00610 
00611    class Example {
00612      public:
00613       void Function(PString arg)
00614       {
00615       }
00616    };
00617 
00618    ...
00619    Example ex;
00620    PString str;
00621    new PThreadObj1Arg<Example>(ex, str, &Example::Function)
00622  */
00623 template <class ObjType, typename Arg1Type>
00624 class PThreadObj1Arg : public PThread
00625 {
00626   PCLASSINFO(PThreadObj1Arg, PThread);
00627   public:
00628     typedef void (ObjType::*ObjTypeFn)(Arg1Type); 
00629     PThreadObj1Arg(ObjType & obj, Arg1Type arg1, ObjTypeFn function, bool autoDelete = false)
00630       : PThread(10000, autoDelete ? PThread::AutoDeleteThread : PThread::NoAutoDeleteThread)
00631       , m_object(obj)
00632       , m_function(function)
00633       , m_arg1(arg1)
00634       { PThread::Resume(); }
00635     PThreadObj1Arg(const char * file, int line, ObjType & obj, Arg1Type arg1, ObjTypeFn function, bool autoDelete = false)
00636       : PThread(10000, autoDelete ? PThread::AutoDeleteThread : PThread::NoAutoDeleteThread, NormalPriority,
00637                 psprintf("%s:%08x-%s:%i", GetClass(), (void *)this, file, line))
00638       , m_object(obj)
00639       , m_function(function)
00640       , m_arg1(arg1)
00641       { PThread::Resume(); }
00642     void Main()
00643     { (m_object.*m_function)(m_arg1); }
00644 
00645   protected:
00646     ObjType & m_object;
00647     ObjTypeFn m_function;
00648     Arg1Type  m_arg1;
00649 };
00650 
00651 template <class ObjType, typename Arg1Type, typename Arg2Type>
00652 class PThreadObj2Arg : public PThread
00653 {
00654   PCLASSINFO(PThreadObj2Arg, PThread);
00655   public:
00656     typedef void (ObjType::*ObjTypeFn)(Arg1Type, Arg2Type); 
00657     PThreadObj2Arg(ObjType & obj, Arg1Type arg1, Arg2Type arg2, ObjTypeFn function, bool autoDelete = false)
00658       : PThread(10000, autoDelete ? PThread::AutoDeleteThread : PThread::NoAutoDeleteThread)
00659       , m_object(obj)
00660       , m_function(function)
00661       , m_arg1(arg1)
00662       , m_arg2(arg2)
00663       { PThread::Resume(); }
00664     PThreadObj2Arg(const char * file, int line, ObjType & obj, Arg1Type arg1, Arg2Type arg2, ObjTypeFn function, bool autoDelete = false)
00665       : PThread(10000, autoDelete ? PThread::AutoDeleteThread : PThread::NoAutoDeleteThread, NormalPriority,
00666                 psprintf("%s:%08x-%s:%i", GetClass(), (void *)this, file, line))
00667       , m_object(obj)
00668       , m_function(function)
00669       , m_arg1(arg1)
00670       , m_arg2(arg2)
00671       { PThread::Resume(); }
00672     void Main()
00673       { (m_object.*m_function)(m_arg1, m_arg2); }
00674 
00675   protected:
00676     ObjType & m_object;
00677     ObjTypeFn m_function;
00678     Arg1Type  m_arg1;
00679     Arg1Type  m_arg2;
00680 };
00681 
00682 
00684 //
00685 // PThreadLocalStorage
00686 //
00687 
00688 #ifdef _WIN32
00689 
00690 #define P_HAS_THREADLOCAL_STORAGE 1
00691 
00692 template <class Storage_T>
00693 class PThreadLocalStorage
00694 {
00695   public:
00696     typedef DWORD Key_T;
00697     typedef Storage_T value_type;
00698 
00699     PThreadLocalStorage()
00700     { key = TlsAlloc(); }
00701 
00702     ~PThreadLocalStorage()
00703     { TlsFree(key);  }
00704 
00705     Key_T GetKey() const
00706     { return key; }
00707 
00708     value_type * Get()
00709     { return (value_type *) TlsGetValue(key); }
00710 
00711     void Set(value_type * v)
00712     { TlsSetValue(key, (LPVOID)v); }
00713 
00714   protected:
00715     DWORD key;
00716 };
00717 
00718 #elif defined(P_PTHREADS)
00719 
00720 #include <pthread.h>
00721 
00722 #define P_HAS_THREADLOCAL_STORAGE 1
00723 
00724 template <class Storage_T>
00725 class PThreadLocalStorage
00726 {
00727   public:
00728     typedef pthread_key_t Key_T;
00729     typedef Storage_T value_type;
00730 
00731     PThreadLocalStorage()
00732     { pthread_key_create(&key, NULL); }
00733 
00734     ~PThreadLocalStorage()
00735     { pthread_key_delete(key); }
00736 
00737     Key_T GetKey() const
00738     { return key; }
00739 
00740     value_type * Get()
00741     { return (value_type *)pthread_getspecific(key); }
00742 
00743     void Set(value_type * v)
00744     { pthread_setspecific(key, v); }
00745 
00746   private:
00747     Key_T key;
00748 };
00749 
00750 #else
00751 
00752 #undef P_HAS_THREADLOCAL_STORAGE 1
00753 #warning("Thread local storage not supported");
00754 
00755 #endif
00756 
00757 
00758 #ifdef _MSC_VER
00759 #pragma warning(default:4355)
00760 #endif
00761 
00762 #endif // PTLIB_THREAD_H
00763 
00764 // End Of File ///////////////////////////////////////////////////////////////

Generated on Thu May 27 01:36:48 2010 for PTLib by  doxygen 1.4.7