Main Page   Class Hierarchy   Compound List   File List   Compound Members   File Members  

threadableobject.h

Go to the documentation of this file.
00001 /*
00002 ** ThreadableObject is a base class for objects that are intended to
00003 **                  internally spawn processing threads to execute
00004 **                  specific member methods....a common example would be
00005 **                  a multi-threaded server.
00006 **                  This is needed because C++ member functions do not
00007 **                  have the signature required by thread-spawning
00008 **                  library functions.
00009 **
00010 **
00011 **   Derive the object class from ThreadableObject, and implement
00012 **     the class's StartThreadFunc method (this is the method through
00013 **     which a newly spawned thread reenters the class code).
00014 **   At the locations in the new class where a handler thread is to be
00015 **     spawned, set any appropriate variables (see discussion below),
00016 **     then call StartThreadWithArg() or StartThread().
00017 **
00018 **   Any method to be executed by a spawned thread should generally
00019 **     have the signature:  THR_RTR func(void *).  That is, it returns void
00020 **     and takes one parameter that is a void pointer.  The parameter is
00021 **     not strictly required, but it can simplify coding under one set
00022 **     of circumstances.
00023 **   The spawning process allows a single void pointer parameter to be
00024 **     passed to a new thread.  Even if a method to be executed by a
00025 **     spawned thread needs no parameters, the void pointer must still
00026 **     be passed, even as NULL.  Keep in mind that
00027 **   If there will be more than one function that might be executed by
00028 **     a spawned thread, then there must be some way for a thread
00029 **     to determine which method to enter.  One way to do this is
00030 **     by using a member variable (possibly with a static mutex).
00031 **     The method might also be indicated as part of a structure
00032 **     passed to the spawning code through the void pointer parameter.
00033 **   In some cases, the simplest routing code might result with an
00034 **     implementation that uses a pointer to class member function:
00035 **     <return_type>(<class_name>::*<pointer_type_name>)(<argument_list>)
00036 **     All of the methods pointed to by this pointer type must have the
00037 **     same signature.  If they all really need different parameters,
00038 **     then designing them all to accept a single void pointer parameter
00039 **     will make them look the same.  Using this method, just before calling
00040 **     StartThreadWithArg, set the static method pointer to
00041 **     point at the desired method:
00042 **       <my_member_pointer> = &<class_name>::<method_name>
00043 **     and in the StartThreadFunc, dereference the member pointer:
00044 **       (this->*<my_member_pointer>)(p_arg)
00045 **     note that in this call, p_arg is the void pointer passed through
00046 **     the spawn process -- just that some of the methods might use it and
00047 **     some might not.
00048 **     The reason why this is a simplification is that the code in
00049 **     the StartThreadFunc method does not have to decode the correct
00050 **     method to call based upon the void pointer contents, or any
00051 **     other variables -- it is implicit within the member method pointer.
00052 **     So, this implementation would be appropriate if the logic for
00053 **     determining which method a new thread should execute is complex.
00054 */
00055 //---------------------------------------------------------------------------
00056 #ifndef threadableobjectH
00057 #define threadableobjectH
00058 //---------------------------------------------------------------------------
00059 #include <worm_statuscode.h>
00060 #include <mutex.h>
00061 
00062 
00063 //---------------------------------------------------------------------------
00064 
00065 #if defined(_WINNT) || defined(_Windows)  // - - - - - - - - - - - - - - - - - - - - - - -
00066 
00067 
00068 #include <windows.h>
00069 #include <process.h>
00070 
00071 #include <stddef.h>
00072 
00073 typedef unsigned int TO_STACK_SIZE;
00074 typedef long         TO_THREAD_ID;
00075 
00076 
00077 #define THREAD_RETURN void         //     Thread functions return this
00078 
00079 
00080 
00081 #elif defined(_SOLARIS)  // - - - - - - - - - - - - - - - - - - - - - - -
00082 
00083 
00084 #include <stdio.h>
00085 
00086 #include <sys/types.h>
00087 #include <thread.h>
00088 
00089 typedef size_t       TO_STACK_SIZE;  // or is it unsigned int?
00090 typedef thread_t     TO_THREAD_ID;
00091 
00092 
00093 typedef void THREAD_RETURN;         //     Thread functions return this
00094 
00095 
00096 #else                   // - - - - - - - - - - - - - - - - - - - - - - -
00097 
00098 #error threadableobject.h not complete for this O/S
00099 
00100 #endif  // - - - - - - - - - - - - - - - - - - - - - - -
00101 
00102 //---------------------------------------------------------------------------
00103 
00104 
00105 
00106 class ThreadableObject
00107 {
00108 protected:
00109 
00110    /*
00111    ** StartThreadWithArg() -- start a new thread with argument(s)
00112    **
00113    **  Arguments:
00114    **     stack_size: Stack size of new thread in bytes
00115    **                 If 0, stack size is set to 8192.
00116    **                 In OS2, 4096 or 8192 is recommended.
00117    **                 In SOLARIS, this argument is ignored
00118    **                 In Windows NT, if stack_size=0, use the stack
00119    **                 size of the calling thread.
00120    **     thread_id:  Thread identification number returned to
00121    **                 calling program.
00122    **     arg:        an unsigned long (void*) passed to the thread.
00123    **     p_isdaemon  start the thread/process as a daemon
00124    **                 rather than internal thread (Solaris only)
00125    **
00126    **  Returns:
00127    **     WORM_STAT_FAILURE if error
00128    **     WORM_STAT_SUCCESS if ok
00129    */
00130 
00131    WORM_STATUS_CODE StartThreadWithArg( TO_STACK_SIZE   stack_size
00132                                       , TO_THREAD_ID  * thread_id
00133                                       , void *          arg
00134 #ifdef _SOLARIS
00135                                       , bool            p_isdaemon = false
00136 #endif
00137                                       );
00138 
00139    /*
00140    ** StartThread() -- start a new thread with no arguments
00141    **
00142    **  Arguments:
00143    **     stack_size: Stack size of new thread in bytes
00144    **                 If 0, stack size is set to 8192.
00145    **                 In OS2, 4096 or 8192 is recommended.
00146    **                 In SOLARIS, this argument is ignored
00147    **                 In Windows NT, if stack_size=0, use the stack
00148    **                 size of the calling thread.
00149    **     thread_id:  Thread identification number returned to
00150    **                 calling program.
00151    **
00152    **  Returns:
00153    **     WORM_STAT_FAILURE if error
00154    **     WORM_STAT_SUCCESS if ok
00155    */
00156 
00157    WORM_STATUS_CODE StartThread( TO_STACK_SIZE   stack_size
00158                                , TO_THREAD_ID  * thread_id
00159 #ifdef _SOLARIS
00160                                , bool            p_isdaemon = false
00161 #endif
00162                                )
00163    {
00164       return StartThreadWithArg( stack_size
00165                                , thread_id
00166                                , NULL
00167 #ifdef _SOLARIS
00168                                , p_isdaemon
00169 #endif
00170                                );
00171    }
00172 
00173    /*
00174    **  KillSelfThread() -- Exit thread without effecting
00175    **                      other threads
00176    */
00177 
00178    static void KillSelfThread();
00179 
00180    /*
00181    **  WaitForThread() -- wait for thread to terminate
00182    **
00183    **  Returns:
00184    **    WORM_STAT_FAILURE if error
00185    **    WORM_STAT_SUCCESS if ok
00186    */
00187    static int WaitForThread( TO_THREAD_ID * thread_id );
00188 
00189    /*
00190    ** KillThread() -- force immediate, unclean, thread exit
00191    **
00192    **  Windows NT documentation gives a strong warning against
00193    **  using TerminateThread(), since no stack cleanup, etc,
00194    **  is done.
00195    **
00196    ** Argument:
00197    **    tid = id of thread to kill
00198    **
00199    ** Returns:
00200    **    WORM_STAT_SUCCESS if ok
00201    **    WORM_STAT_FAILURE if an error
00202    */
00203    static int KillThread(  TO_THREAD_ID tid );
00204 
00205 
00206    // That -- Pointer to the ThreadableObject requesting a
00207    //         new internal thread.
00208    //
00209    static ThreadableObject * That;
00210 
00211    // ThatMutex -- access lock for That pointer memory
00212    //
00213    static TMutex * ThatMutex;
00214 
00215 public:
00216 
00217    ThreadableObject()
00218    {
00219       if ( ThatMutex == NULL )
00220       {
00221          ThatMutex = new TMutex("ThreadMutex");
00222       }
00223    }
00224 
00225    // GetThat() -- Method used by the file-scope function
00226    //              StartObjectThread() to access the "That"
00227    //              pointer which is the object requesting
00228    //              the thread start.
00229    //
00230    static ThreadableObject * GetThat() { return That; }
00231 
00232    /* StartThreadFunc() -- Method through which a newly-spawned
00233    **                      thread returns to the "That" object
00234    **                      to start execution.
00235    **
00236    ** PARAMETERS:
00237    **      p_argument = pointer to any object containing
00238    **                   requisite unique start conditions to
00239    **                   the thread, possibly including
00240    **                   indication of which method to execute.
00241    */
00242    virtual void StartThreadFunc( void * p_argument ) = 0;
00243 };
00244 
00245 #endif
00246 

Generated on Tue May 6 09:16:11 2003 for Earthworm Libs by doxygen1.3-rc3