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 Windows 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  * $Log: thread.h,v $
00030  * Revision 1.54  2007/09/17 11:14:42  rjongbloed
00031  * Added "No Trace" build configuration.
00032  *
00033  * Revision 1.53  2007/09/17 05:30:43  rjongbloed
00034  * Added thread local storage in tracing to avoid a certain class of deadlocks.
00035  *
00036  * Revision 1.52  2007/07/08 23:54:53  rjongbloed
00037  * Fixed MSVC warnings
00038  *
00039  * Revision 1.51  2007/07/06 02:11:48  csoutheren
00040  * Add extra memory leak debugging on Linux
00041  * Remove compile warnings
00042  *
00043  * Revision 1.50  2007/06/25 20:17:35  csoutheren
00044  * Add ability to specify thread name
00045  *
00046  * Revision 1.49  2007/02/20 04:37:22  csoutheren
00047  * Fix for gcc
00048  *
00049  * Revision 1.48  2007/02/20 04:24:46  csoutheren
00050  * More rationalisation of PThread templates
00051  *
00052  * Revision 1.47  2007/02/19 04:38:15  csoutheren
00053  * Rationalised and documented thread creation templates
00054  *
00055  * Revision 1.46  2006/10/03 06:30:31  csoutheren
00056  * Fix error in PThreadObj templates
00057  *
00058  * Revision 1.45  2006/07/05 09:14:29  csoutheren
00059  * Fixed startup problems with using Resume in PThread descendants
00060  *
00061  * Revision 1.44  2006/07/05 03:59:19  csoutheren
00062  * Fix PThreadMain2Arg template
00063  *
00064  * Revision 1.43  2006/06/28 11:28:21  csoutheren
00065  * Patch 1456858 - increase default thread stack size
00066  * Thanks to drosario
00067  *
00068  * Revision 1.42  2006/05/25 23:28:27  csoutheren
00069  * Fixed compilation under gcc 4.0
00070  *
00071  * Revision 1.41  2006/05/23 22:11:27  csoutheren
00072  * Fixed compilation under gcc
00073  *
00074  * Revision 1.40  2006/05/23 00:58:05  csoutheren
00075  * Add templates for creating threads
00076  *
00077  * Revision 1.39  2006/01/29 22:35:46  csoutheren
00078  * Added fix for thread termination problems on SMP machines
00079  * Thanks to Derek Smithies
00080  *
00081  * Revision 1.38  2006/01/11 22:27:44  dereksmithies
00082  * Add extra comments describing the usage of Resume() in the constructor of a
00083  * class descended of PThread
00084  *
00085  * Revision 1.37  2005/11/30 12:47:38  csoutheren
00086  * Removed tabs, reformatted some code, and changed tags for Doxygen
00087  *
00088  * Revision 1.36  2005/11/25 03:43:47  csoutheren
00089  * Fixed function argument comments to be compatible with Doxygen
00090  *
00091  * Revision 1.35  2003/10/08 21:39:34  dereksmithies
00092  * Add a #define to cope with backward compatability issues for PThreadIdentifier
00093  * Thanks to Andrey S Pankov and Craig Southeren for their input.
00094  *
00095  * Revision 1.34  2003/09/17 05:41:59  csoutheren
00096  * Removed recursive includes
00097  *
00098  * Revision 1.33  2003/09/17 01:18:02  csoutheren
00099  * Removed recursive include file system and removed all references
00100  * to deprecated coooperative threading support
00101  *
00102  * Revision 1.32  2002/10/04 04:33:27  robertj
00103  * Added functions for getting operating system thread identifier values.
00104  *
00105  * Revision 1.31  2002/09/16 01:08:59  robertj
00106  * Added #define so can select if #pragma interface/implementation is used on
00107  *   platform basis (eg MacOS) rather than compiler, thanks Robert Monaghan.
00108  *
00109  * Revision 1.30  2002/06/27 06:44:28  robertj
00110  * Changed "" to PString::Empty() where assigning to PString.
00111  *
00112  * Revision 1.29  2002/04/24 01:49:22  robertj
00113  * Fixed error in PTRACE_BLOCk nesting level to now work when no tracing enabled.
00114  *
00115  * Revision 1.28  2002/04/24 01:09:56  robertj
00116  * Fixed problem with PTRACE_BLOCK indent level being correct across threads.
00117  *
00118  * Revision 1.27  2001/09/10 02:51:22  robertj
00119  * Major change to fix problem with error codes being corrupted in a
00120  *   PChannel when have simultaneous reads and writes in threads.
00121  *
00122  * Revision 1.26  2001/05/22 12:49:32  robertj
00123  * Did some seriously wierd rewrite of platform headers to eliminate the
00124  *   stupid GNU compiler warning about braces not matching.
00125  *
00126  * Revision 1.25  2000/11/28 12:55:36  robertj
00127  * Added static function to create a new thread class and automatically
00128  *   run a function on another class in the context of that thread.
00129  *
00130  * Revision 1.24  2000/10/20 05:31:09  robertj
00131  * Added function to change auto delete flag on a thread.
00132  *
00133  * Revision 1.23  2000/06/26 11:17:19  robertj
00134  * Nucleus++ port (incomplete).
00135  *
00136  * Revision 1.22  2000/02/29 12:26:14  robertj
00137  * Added named threads to tracing, thanks to Dave Harvey
00138  *
00139  * Revision 1.21  1999/06/06 05:07:17  robertj
00140  * Fixed documentation error.
00141  *
00142  * Revision 1.20  1999/03/09 02:59:51  robertj
00143  * Changed comments to doc++ compatible documentation.
00144  *
00145  * Revision 1.19  1999/02/16 08:11:17  robertj
00146  * MSVC 6.0 compatibility changes.
00147  *
00148  * Revision 1.18  1998/11/20 03:18:33  robertj
00149  * Added thread WaitForTermination() function.
00150  *
00151  * Revision 1.17  1998/10/31 12:47:59  robertj
00152  * Removed ability to start threads immediately, race condition with vtable (Main() function).
00153  *
00154  * Revision 1.16  1998/09/23 06:21:41  robertj
00155  * Added open source copyright license.
00156  *
00157  * Revision 1.15  1996/03/02 03:15:51  robertj
00158  * Added automatic deletion of thread object instances on thread completion.
00159  *
00160  * Revision 1.14  1995/12/10 11:44:32  robertj
00161  * Fixed bug in non-platform threads and semaphore timeouts.
00162  *
00163  * Revision 1.13  1995/11/21 11:49:44  robertj
00164  * Added timeout on semaphore wait.
00165  *
00166  * Revision 1.12  1995/07/31 12:10:40  robertj
00167  * Added semaphore class.
00168  *
00169  * Revision 1.11  1995/06/17 11:13:35  robertj
00170  * Documentation update.
00171  *
00172  * Revision 1.10  1995/03/14 12:42:49  robertj
00173  * Updated documentation to use HTML codes.
00174  *
00175  * Revision 1.9  1995/01/16  09:42:13  robertj
00176  * Documentation.
00177  *
00178  * Revision 1.8  1994/09/25  10:45:22  robertj
00179  * Virtualised IsNoLongerBlocked for unix platform.
00180  *
00181  * Revision 1.6  1994/08/22  00:46:48  robertj
00182  * Added pragma fro GNU C++ compiler.
00183  *
00184  * Revision 1.5  1994/08/21  23:43:02  robertj
00185  * Added SuspendBlock state to cooperative multi-threading to fix logic fault.
00186  *
00187  * Revision 1.4  1994/08/04  12:32:22  robertj
00188  * Better name of thread block check function.
00189  *
00190  * Revision 1.3  1994/07/21  12:33:49  robertj
00191  * Moved cooperative threads to common.
00192  *
00193  * Revision 1.2  1994/07/02  03:03:49  robertj
00194  * Added restartable threads.
00195  *
00196  * Revision 1.1  1994/06/25  11:55:15  robertj
00197  * Initial revision
00198  *
00199  */
00200 
00201 #ifndef _PTHREAD
00202 #define _PTHREAD
00203 
00204 #ifdef P_USE_PRAGMA
00205 #pragma interface
00206 #endif
00207 
00208 #ifdef Priority
00209 #undef Priority
00210 #endif
00211 
00212 class PSemaphore;
00213 
00214 #define PThreadIdentifer PThreadIdentifier
00215 
00216 typedef P_THREADIDENTIFIER PThreadIdentifier;
00217 
00219 // PThread
00220 
00234 class PThread : public PObject
00235 {
00236   PCLASSINFO(PThread, PObject);
00237 
00238   public:
00241 
00242     enum Priority {
00244       LowestPriority,   
00245 
00247       LowPriority,      
00248 
00250       NormalPriority,   
00251 
00253       HighPriority,     
00254 
00256       HighestPriority,  
00257 
00258       NumPriorities
00259     };
00260 
00262     enum AutoDeleteFlag {
00264       AutoDeleteThread,   
00265 
00267       NoAutoDeleteThread  
00268     };
00269 
00292     PThread(
00293       PINDEX ,                 
00294       AutoDeleteFlag deletion = AutoDeleteThread,
00296       Priority priorityLevel = NormalPriority,  
00297       const PString & threadName = PString::Empty() 
00298     );
00299 
00307     ~PThread();
00309 
00316     void PrintOn(
00317       ostream & strm    
00318     ) const;
00320 
00328     virtual void Restart();
00329 
00341     virtual void Terminate();
00342 
00348     virtual BOOL IsTerminated() const;
00349 
00355     void WaitForTermination() const;
00356     BOOL WaitForTermination(
00357       const PTimeInterval & maxWait  
00358     ) const;
00359 
00372     virtual void Suspend(
00373       BOOL susp = TRUE    
00374     );
00375 
00395     virtual void Resume();
00396 
00404     virtual BOOL IsSuspended() const;
00405 
00407     static void Sleep(
00408       const PTimeInterval & delay   
00409     );
00410 
00414     virtual void SetPriority(
00415       Priority priorityLevel    
00416     );
00417 
00423     virtual Priority GetPriority() const;
00424 
00428     virtual void SetAutoDelete(
00429       AutoDeleteFlag deletion = AutoDeleteThread  
00430     );
00431 
00435     void SetNoAutoDelete() { SetAutoDelete(NoAutoDeleteThread); }
00436 
00442     virtual PString GetThreadName() const;
00443 
00449     virtual void SetThreadName(
00450       const PString & name        
00451     );
00453 
00461     virtual PThreadIdentifier GetThreadId() const;
00462     static PThreadIdentifier GetCurrentThreadId();
00463 
00471     virtual void Main() = 0;
00472 
00482     static PThread * Current();
00483 
00490     static void Yield();
00491 
00496     static PThread * Create(
00497       const PNotifier & notifier,     
00498       INT parameter = 0,              
00499       AutoDeleteFlag deletion = AutoDeleteThread,
00501       Priority priorityLevel = NormalPriority,  
00502       const PString & threadName = PString::Empty(), 
00503       PINDEX stackSize = 65536         
00504     );
00506 
00507   protected:
00508     void InitialiseProcessThread();
00509     /* Initialialise the primordial thread, the one in the PProcess. This is
00510        required due to the bootstrap logic of processes and threads.
00511      */
00512 
00513   private:
00514     PThread();
00515     // Create a new thread instance as part of a PProcess class.
00516 
00517     friend class PProcess;
00518     // So a PProcess can get at PThread() constructor but nothing else.
00519 
00520     PThread(const PThread &) { }
00521     // Empty constructor to prevent copying of thread instances.
00522 
00523     PThread & operator=(const PThread &) { return *this; }
00524     // Empty assignment operator to prevent copying of thread instances.
00525 
00526     BOOL autoDelete;
00527     // Automatically delete the thread on completion.
00528 
00529     // Give the thread a name for debugging purposes.
00530     PString threadName;
00531 
00532   private:
00533 #if PTRACING
00534     PStack<PStringStream> traceStreams;
00535     unsigned traceLevel;
00536     friend class PTrace;
00537 
00538     unsigned traceBlockIndentLevel;
00539     friend class PTrace::Block;
00540 #endif
00541 
00542 
00543 // Include platform dependent part of class
00544 #ifdef _WIN32
00545 #include "msos/ptlib/thread.h"
00546 #else
00547 #include "unix/ptlib/thread.h"
00548 #endif
00549 };
00550 
00551 #ifdef _MSC_VER
00552 #pragma warning(disable:4355)
00553 #endif
00554 
00559 /*
00560    This class automates calling a global function with no arguments within it's own thread.
00561    It is used as follows:
00562 
00563    void GlobalFunction()
00564    {
00565    }
00566 
00567    ...
00568    PString arg;
00569    new PThreadMain(&GlobalFunction)
00570  */
00571 class PThreadMain : public PThread
00572 {
00573   PCLASSINFO(PThreadMain, PThread);
00574   public:
00575     typedef void (*FnType)(); 
00576     PThreadMain(FnType _fn, BOOL autoDelete = FALSE)
00577       : PThread(10000, autoDelete ? PThread::AutoDeleteThread : PThread::NoAutoDeleteThread), fn(_fn)
00578     { PThread::Resume(); }
00579     PThreadMain(const char * _file, int _line, FnType _fn, BOOL autoDelete = FALSE)
00580       : PThread(10000, autoDelete ? PThread::AutoDeleteThread : PThread::NoAutoDeleteThread,  NormalPriority,
00581         psprintf("%s:%08x-%s:%i", GetClass(), (void *)this, _file, _line)), fn(_fn)
00582     { PThread::Resume(); }
00583     virtual void Main()
00584     { (*fn)(); }
00585     FnType fn;
00586 };
00587 
00588 /*
00589    This template automates calling a global function with one argument within it's own thread.
00590    It is used as follows:
00591 
00592    void GlobalFunction(PString arg)
00593    {
00594    }
00595 
00596    ...
00597    PString arg;
00598    new PThread1Arg<PString>(arg, &GlobalFunction)
00599  */
00600 template<typename Arg1Type>
00601 class PThread1Arg : public PThread
00602 {
00603   PCLASSINFO(PThread1Arg, PThread);
00604   public:
00605     typedef void (*FnType)(Arg1Type arg1); 
00606     PThread1Arg(Arg1Type _arg1, FnType _fn, BOOL autoDelete = FALSE)
00607       : PThread(10000, autoDelete ? PThread::AutoDeleteThread : PThread::NoAutoDeleteThread), fn(_fn),
00608         arg1(_arg1)
00609     { PThread::Resume(); }
00610     PThread1Arg(const char * _file, int _line, Arg1Type _arg1, FnType _fn, BOOL autoDelete = FALSE)
00611       : PThread(10000, autoDelete ? PThread::AutoDeleteThread : PThread::NoAutoDeleteThread,  NormalPriority,
00612         psprintf("%s:%08x-%s:%i", GetClass(), (void *)this, _file, _line)), fn(_fn),
00613         arg1(_arg1)
00614     { PThread::Resume(); }
00615     virtual void Main()
00616     { (*fn)(arg1); }
00617     FnType fn;
00618     Arg1Type arg1;
00619 };
00620 
00621 
00622 /*
00623    This template automates calling a global function with two arguments within it's own thread.
00624    It is used as follows:
00625 
00626    void GlobalFunction(PString arg1, int arg2)
00627    {
00628    }
00629 
00630    ...
00631    PString arg;
00632    new PThread2Arg<PString, int>(arg, &GlobalFunction)
00633  */
00634 template<typename Arg1Type, typename Arg2Type>
00635 class PThread2Arg : public PThread
00636 {
00637   PCLASSINFO(PThread2Arg, PThread);
00638   public:
00639     typedef void (*FnType)(Arg1Type arg1, Arg2Type arg2); 
00640     PThread2Arg(Arg1Type _arg1, Arg2Type _arg2, FnType _fn, BOOL autoDelete = FALSE)
00641       : PThread(10000, autoDelete ? PThread::AutoDeleteThread : PThread::NoAutoDeleteThread), fn(_fn),
00642         arg1(_arg1), arg2(_arg2)
00643     { PThread::Resume(); }
00644     PThread2Arg(const char * _file, int _line, Arg1Type _arg1, Arg2Type _arg2, FnType _fn, BOOL autoDelete = FALSE)
00645       : PThread(10000, autoDelete ? PThread::AutoDeleteThread : PThread::NoAutoDeleteThread, NormalPriority,
00646         psprintf("%s:%08x-%s:%i", GetClass(), (void *)this, _file, _line)), fn(_fn),
00647         arg1(_arg1), arg2(_arg2)
00648     { PThread::Resume(); }
00649     virtual void Main()
00650     { (*fn)(arg1, arg2); }
00651     FnType fn;
00652     Arg1Type arg1;
00653     Arg2Type arg2;
00654 };
00655 
00656 /*
00657    This template automates calling a member function with no arguments within it's own thread.
00658    It is used as follows:
00659 
00660    class Example {
00661      public:
00662       void Function()
00663       {
00664       }
00665    };
00666 
00667    ...
00668    Example ex;
00669    new PThreadObj<Example>(ex, &Example::Function)
00670  */
00671 
00672 template <typename ObjType>
00673 class PThreadObj : public PThread
00674 {
00675   public:
00676   PCLASSINFO(PThreadObj, PThread);
00677   public:
00678     typedef void (ObjType::*ObjTypeFn)(); 
00679     PThreadObj(ObjType & _obj, ObjTypeFn _fn, BOOL autoDelete = FALSE)
00680       : PThread(10000, autoDelete ? PThread::AutoDeleteThread : PThread::NoAutoDeleteThread),
00681         obj(_obj), fn(_fn)
00682     { PThread::Resume(); }
00683     PThreadObj(const char * _file, int _line, ObjType & _obj, ObjTypeFn _fn, BOOL autoDelete = FALSE)
00684       : PThread(10000, autoDelete ? PThread::AutoDeleteThread : PThread::NoAutoDeleteThread, NormalPriority,
00685         psprintf("%s:%08x-%s:%i", GetClass(), (void *)this, _file, _line)),
00686         obj(_obj), fn(_fn)
00687     { PThread::Resume(); }
00688     void Main()
00689     { (obj.*fn)(); }
00690 
00691   protected:
00692     ObjType & obj;
00693     ObjTypeFn fn;
00694 };
00695 
00696 
00697 /*
00698    This template automates calling a member function with one argument within it's own thread.
00699    It is used as follows:
00700 
00701    class Example {
00702      public:
00703       void Function(PString arg)
00704       {
00705       }
00706    };
00707 
00708    ...
00709    Example ex;
00710    PString str;
00711    new PThreadObj1Arg<Example>(ex, str, &Example::Function)
00712  */
00713 template <class ObjType, typename Arg1Type>
00714 class PThreadObj1Arg : public PThread
00715 {
00716   PCLASSINFO(PThreadObj1Arg, PThread);
00717   public:
00718     typedef void (ObjType::*ObjTypeFn)(Arg1Type); 
00719     PThreadObj1Arg(ObjType & _obj, Arg1Type _arg1, ObjTypeFn _fn, BOOL autoDelete = FALSE)
00720       : PThread(10000, autoDelete ? PThread::AutoDeleteThread : PThread::NoAutoDeleteThread),
00721                                 obj(_obj), fn(_fn), arg1(_arg1)
00722     { PThread::Resume(); }
00723     PThreadObj1Arg(const char * _file, int _line, ObjType & _obj, Arg1Type _arg1, ObjTypeFn _fn, BOOL autoDelete = FALSE)
00724       : PThread(10000, autoDelete ? PThread::AutoDeleteThread : PThread::NoAutoDeleteThread, NormalPriority,
00725                                 psprintf("%s:%08x-%s:%i", GetClass(), (void *)this, _file, _line)),
00726                                 obj(_obj), fn(_fn), arg1(_arg1)
00727     { PThread::Resume(); }
00728     void Main()
00729     { (obj.*fn)(arg1); }
00730 
00731   protected:
00732     ObjType & obj;
00733     ObjTypeFn fn;
00734     Arg1Type arg1;
00735 };
00736 
00737 #ifdef _MSC_VER
00738 #pragma warning(default:4355)
00739 #endif
00740 
00741 #endif // _PTHREAD
00742 
00743 // End Of File ///////////////////////////////////////////////////////////////

Generated on Fri Mar 7 06:25:03 2008 for PTLib by  doxygen 1.5.1