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: 22881 $
00030  * $Author: rjongbloed $
00031  * $Date: 2009-06-14 09:39:23 +0000 (Sun, 14 Jun 2009) $
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 autoDel = false)
00427       : PThread(10000, autoDel ? PThread::AutoDeleteThread : PThread::NoAutoDeleteThread)
00428       , m_function(function)
00429       { PThread::Resume(); }
00430     PThreadMain(const char * file, int line, FnType function, bool autoDel = false)
00431       : PThread(10000, autoDel ? 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 autoDel = false)
00462       : PThread(10000, autoDel ? 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 autoDel = false)
00467       : PThread(10000, autoDel ? 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 autoDel = false)
00500       : PThread(10000, autoDel ? 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 autoDel = false)
00506       : PThread(10000, autoDel ? 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 autoDel = false)
00540       : PThread(10000, autoDel ? 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 autoDel = false)
00547       : PThread(10000, autoDel ? 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     PCLASSINFO(PThreadObj, PThread);
00584   public:
00585     typedef void (ObjType::*ObjTypeFn)(); 
00586 
00587     PThreadObj(
00588       ObjType & obj,
00589       ObjTypeFn function,
00590       bool autoDel = false,
00591       const char * name = NULL,
00592       PThread::Priority priority = PThread::NormalPriority
00593     ) : PThread(10000,
00594                 autoDel ? PThread::AutoDeleteThread : PThread::NoAutoDeleteThread,
00595                 priority,
00596                 name)
00597       , m_object(obj)
00598       , m_function(function)
00599     {
00600       PThread::Resume();
00601     }
00602 
00603     void Main()
00604     {
00605       (m_object.*m_function)();
00606     }
00607 
00608   protected:
00609     ObjType & m_object;
00610     ObjTypeFn m_function;
00611 };
00612 
00613 
00614 /*
00615    This template automates calling a member function with one argument within it's own thread.
00616    It is used as follows:
00617 
00618    class Example {
00619      public:
00620       void Function(PString arg)
00621       {
00622       }
00623    };
00624 
00625    ...
00626    Example ex;
00627    PString str;
00628    new PThreadObj1Arg<Example>(ex, str, &Example::Function)
00629  */
00630 template <class ObjType, typename Arg1Type>
00631 class PThreadObj1Arg : public PThread
00632 {
00633     PCLASSINFO(PThreadObj1Arg, PThread);
00634   public:
00635     typedef void (ObjType::*ObjTypeFn)(Arg1Type); 
00636 
00637     PThreadObj1Arg(
00638       ObjType & obj,
00639       Arg1Type arg1,
00640       ObjTypeFn function,
00641       bool autoDel = false,
00642       const char * name = NULL,
00643       PThread::Priority priority = PThread::NormalPriority
00644     ) : PThread(10000,
00645                 autoDel ? PThread::AutoDeleteThread : PThread::NoAutoDeleteThread,
00646                 priority,
00647                 name)
00648       , m_object(obj)
00649       , m_function(function)
00650       , m_arg1(arg1)
00651     {
00652       PThread::Resume();
00653     }
00654 
00655     void Main()
00656     {
00657       (m_object.*m_function)(m_arg1);
00658     }
00659 
00660   protected:
00661     ObjType & m_object;
00662     ObjTypeFn m_function;
00663     Arg1Type  m_arg1;
00664 };
00665 
00666 template <class ObjType, typename Arg1Type, typename Arg2Type>
00667 class PThreadObj2Arg : public PThread
00668 {
00669     PCLASSINFO(PThreadObj2Arg, PThread);
00670   public:
00671     typedef void (ObjType::*ObjTypeFn)(Arg1Type, Arg2Type);
00672 
00673     PThreadObj2Arg(
00674       ObjType & obj,
00675       Arg1Type arg1,
00676       Arg2Type arg2,
00677       ObjTypeFn function,
00678       bool autoDel = false,
00679       const char * name = NULL,
00680       PThread::Priority priority = PThread::NormalPriority
00681     ) : PThread(10000,
00682                 autoDel ? PThread::AutoDeleteThread : PThread::NoAutoDeleteThread,
00683                 priority,
00684                 name)
00685       , m_object(obj)
00686       , m_function(function)
00687       , m_arg1(arg1)
00688       , m_arg2(arg2)
00689     {
00690       PThread::Resume();
00691     }
00692 
00693     void Main()
00694     {
00695       (m_object.*m_function)(m_arg1, m_arg2);
00696     }
00697 
00698   protected:
00699     ObjType & m_object;
00700     ObjTypeFn m_function;
00701     Arg1Type  m_arg1;
00702     Arg2Type  m_arg2;
00703 };
00704 
00705 
00707 //
00708 // PThreadLocalStorage
00709 //
00710 
00711 #ifdef _WIN32
00712 
00713 #define P_HAS_THREADLOCAL_STORAGE 1
00714 
00715 template <class Storage_T>
00716 class PThreadLocalStorage
00717 {
00718   public:
00719     typedef DWORD Key_T;
00720     typedef Storage_T value_type;
00721 
00722     PThreadLocalStorage()
00723     { key = TlsAlloc(); }
00724 
00725     ~PThreadLocalStorage()
00726     { TlsFree(key);  }
00727 
00728     Key_T GetKey() const
00729     { return key; }
00730 
00731     value_type * Get()
00732     { return (value_type *) TlsGetValue(key); }
00733 
00734     void Set(value_type * v)
00735     { TlsSetValue(key, (LPVOID)v); }
00736 
00737   protected:
00738     DWORD key;
00739 };
00740 
00741 #elif defined(P_PTHREADS)
00742 
00743 #include <pthread.h>
00744 
00745 #define P_HAS_THREADLOCAL_STORAGE 1
00746 
00747 template <class Storage_T>
00748 class PThreadLocalStorage
00749 {
00750   public:
00751     typedef pthread_key_t Key_T;
00752     typedef Storage_T value_type;
00753 
00754     PThreadLocalStorage()
00755     { pthread_key_create(&key, NULL); }
00756 
00757     ~PThreadLocalStorage()
00758     { pthread_key_delete(key); }
00759 
00760     Key_T GetKey() const
00761     { return key; }
00762 
00763     value_type * Get()
00764     { return (value_type *)pthread_getspecific(key); }
00765 
00766     void Set(value_type * v)
00767     { pthread_setspecific(key, v); }
00768 
00769   private:
00770     Key_T key;
00771 };
00772 
00773 #else
00774 
00775 #undef P_HAS_THREADLOCAL_STORAGE 1
00776 #warning("Thread local storage not supported");
00777 
00778 #endif
00779 
00780 
00781 #ifdef _MSC_VER
00782 #pragma warning(default:4355)
00783 #endif
00784 
00785 #endif // PTLIB_THREAD_H
00786 
00787 // End Of File ///////////////////////////////////////////////////////////////

Generated on Mon Aug 3 20:41:51 2009 for PTLib by  doxygen 1.5.1