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

threadableobject.cpp

Go to the documentation of this file.
00001 /********************************************
00002 *              worm_threads.c               *
00003 *            Windows NT version             *
00004 *                                           *
00005 * This file contains functions StartThread, *
00006 * WaitThread, and KillThread                *
00007 *********************************************/
00008 //---------------------------------------------------------------------------
00009 #include "threadableobject.h"
00010 
00011 //---------------------------------------------------------------------------
00012 #ifdef _SOLARIS
00013 #include <signal.h>
00014 #endif
00015 
00016 #pragma package(smart_init)
00017 
00018 TMutex * ThreadableObject::ThatMutex = NULL;
00019 ThreadableObject * ThreadableObject::That = NULL;
00020 
00021 //---------------------------------------------------------------------------
00022 #ifdef _SOLARIS
00023 /*
00024 ** SignalHandler() -- Solaris-specific signal handler
00025 **
00026 **  Added for use with the KillThread function so that
00027 **  killed threads will exit gracefully
00028 */
00029 static void ThreadableSigHandler( int p_sig )
00030 {
00031    void * status;
00032 
00033    switch (p_sig)
00034    {
00035       case SIGUSR1:
00036            // DEBUG
00037            // printf( "thread %d caught SIGUSR1; calling thr_exit()\n"
00038            //       , (int)thr_self()
00039            //       );
00040            thr_exit( status );
00041    }
00042 }
00043 #endif
00044 
00045 //---------------------------------------------------------------------------
00046 // StartThreadableObject() -- this is a helper function, used only in this file,
00047 //                            that has the signature type required by the
00048 //                            _beginthread() function.
00049 //
00050 //                            It is important that sufficient time between
00051 //                            calls to this function be allowed to prevent
00052 //                            conflicts with the class-scope variable
00053 //                            'That' (accessed with ::GetThat).
00054 //                            Generally, sleeping 1/4 - 1/2 second after
00055 //                            calls to StartThread()
00056 //                            or StartThreadWithArg() will suffice.
00057 //
00058 static void StartObjectThread( void * p_argument )
00059 {
00060    if ( ThreadableObject::GetThat() != NULL )
00061    {
00062       ThreadableObject::GetThat()->StartThreadFunc(p_argument);
00063    }
00064 }
00065 
00066 //---------------------------------------------------------------------------
00067 WORM_STATUS_CODE ThreadableObject::StartThreadWithArg( TO_STACK_SIZE   p_stack_size
00068                                                      , TO_THREAD_ID  * thread_id
00069                                                      , void *          p_parameters
00070 #ifdef _SOLARIS
00071                                                      , bool            p_isdaemon = false
00072 #endif
00073                                                      )
00074 {
00075 #if defined(_WINNT) || defined(_Windows)
00076    long tid = -1;
00077 
00078    // Use mutex to keep global "That" from being clobbered.
00079    ThatMutex->RequestLock();
00080    That = this;
00081    tid = _beginthread( StartObjectThread, p_stack_size, p_parameters );
00082    ThatMutex->ReleaseLock();
00083 
00084    if ( tid == -1 )
00085    {
00086       // Couldn't create thread
00087       return WORM_STAT_FAILURE;
00088    }
00089 
00090 #elif defined(_SOLARIS)
00091 
00092    int rc;              // Function return code
00093    TO_THREAD_ID tid;     // working thread id
00094 
00095    // Set up a signal-handling function to be inherited by threads
00096    // used by the KillThread() method
00097    sigset( SIGUSR1, &ThreadableSigHandler );
00098 
00099    // Start the thread
00100    //
00101    // Note: THR_DETACHED is required for thr_exit to work. That is,
00102    //   a detached thread can truly kill itself without lingering in
00103    //   some afterlife, waiting for some other thread to pick up it's exit
00104    //   status before it can truly cease to be...
00105    //
00106    // Use mutex to keep global "That" from being clobbered.
00107    ThatMutex->RequestLock();
00108    That = this;
00109    rc = thr_create( (void *)0
00110                   , p_stack_size
00111                   , StartObjectThread
00112                   , p_parameters
00113                   , THR_DETACHED|THR_NEW_LWP|(p_isdaemon ? THR_DAEMON : 0)
00114                   , &tid
00115                   );
00116    ThatMutex->ReleaseLock();
00117 
00118    if ( rc != 0 )
00119    {
00120       // Couldn't create thread
00121       return WORM_STAT_FAILURE;
00122    }
00123 #endif
00124 
00125    *thread_id = (TO_THREAD_ID)tid;     /* Return the thread id */
00126 
00127    return WORM_STAT_SUCCESS;
00128 }
00129 //---------------------------------------------------------------------------
00130 void ThreadableObject::KillSelfThread( void )
00131 {
00132 #if defined(_WINNT) || defined(_Windows)
00133     _endthread();
00134 #elif defined(_SOLARIS)
00135    thr_exit( (void *)NULL );
00136 #endif
00137 }
00138 //---------------------------------------------------------------------------
00139 int ThreadableObject::WaitForThread( TO_THREAD_ID * thread_id )
00140 {
00141 #if defined(_WINNT) || defined(_Windows)
00142    if ( WaitForSingleObject((HANDLE)(*thread_id), INFINITE ) == WAIT_FAILED )
00143    {
00144       return WORM_STAT_FAILURE;
00145    }
00146 #elif defined(_SOLARIS)
00147    // this is unimplemented within Solaris
00148 #endif
00149    return WORM_STAT_SUCCESS;
00150 }
00151 //---------------------------------------------------------------------------
00152 int ThreadableObject::KillThread( TO_THREAD_ID tid )
00153 {
00154 #if defined(_WINNT) || defined(_Windows)
00155     const DWORD exit_code = 0;
00156 
00157     if ( TerminateThread( (HANDLE)tid, exit_code ) == 0 )
00158     {
00159        return WORM_STAT_FAILURE;
00160     }
00161     return WORM_STAT_SUCCESS;
00162 #elif defined(_SOLARIS)
00163    return( thr_kill( (thread_t) tid, SIGUSR1 ) );
00164 #endif
00165 }
00166 //---------------------------------------------------------------------------

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