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 //---------------------------------------------------------------------------