/*------------------------------------------------------------------------*/ /* */ /* THREAD.H */ /* */ /* Copyright (c) 1993, 1994 Borland International */ /* All Rights Reserved */ /* */ /* Defines the class TMutex and its nested class Lock. */ /* Defines the class TCriticalSection and its nested class Lock. */ /* Defines the class TSync and its nested class Lock. */ /* Defines the template TStaticSync and its nested class Lock. */ /* Defines the class TThread. */ /* */ /*------------------------------------------------------------------------*/ #if !defined( CLASSLIB_THREAD_H ) #define CLASSLIB_THREAD_H #if !defined( __CSTRING_H ) #include #endif #if defined( _Windows ) # if defined( __WINDOWS_H ) # if !defined( STRICT ) # error #define must be preceded by #define STRICT # endif # else # define STRICT # include # endif #elif defined( __OS2__ ) # if defined( __OS2_H ) # if !defined( INCL_BASE ) # error #include must be preceded by #define INCL_PM # endif # else # define INCL_BASE # include # endif #endif #if !defined( __CHECKS_H ) #include #endif // __CHECKS_H #if !defined( CLASSLIB_DEFS_H ) #include #endif #if !defined(BI_MULTI_THREAD) #error Thread classes require multi-threaded operating system. #endif #if defined( BI_CLASSLIB_NO_po ) #pragma option -po- #endif /*------------------------------------------------------------------------*/ /* */ /* class TMutex; */ /* class TMutex::Lock; */ /* */ /* TMutex provides a system-independent interface to critical */ /* sections in threads. With suitable underlying implementations the */ /* same code can be used under OS/2 and Windows NT. */ /* */ /* An object of type TMutex can be used in conjunction with */ /* objects of type TMutex::Lock to guarantee that only one */ /* thread can be executing any of the code sections protected by the */ /* lock at any given time. */ /* */ /* The differences between the classes TCriticalSection and TMutex are */ /* that a timeout can be specified when creating a Lock on a TMutex */ /* object, and that a TMutex object has a HANDLE which can be used */ /* outside the class. This mirrors the distinction made in Windows NT */ /* between a CRITICALSECTION and a Mutex. Under NT a TCriticalSection */ /* object is much faster than a TMutex object. Under operating systems */ /* that don't make this distinction a TCriticalSection object can use */ /* the same underlying implementation as a TMutex, losing the speed */ /* advantage that it has under NT. */ /* */ /* TMutex Public Interface */ /* --------------------------------- */ /* */ /* TMutex(); Constructor. Takes no parameters. */ /* */ /* ~TMutex(); Destructor. */ /* */ /* operator HANDLE() const; (NT) */ /* operator HMTX() const; (OS/2) */ /* Returns a handle to the TMutex object, */ /* for use in OS calls that require it. */ /* */ /* class Lock; Handles locking and unlocking of */ /* critical sections. */ /* */ /* */ /* TMutex::Lock Public Interface */ /* --------------------------------------- */ /* */ /* Lock( const TMutex&, */ /* unsigned long timeOut = NoLimit ); */ /* */ /* Request a lock on the TCriticalSection */ /* object. If no Lock object in a different */ /* thread from the calling thread holds */ /* a lock on that object the lock is */ /* allowed and execution continues. If */ /* another thread holds a lock on that */ /* object the requesting thread is blocked */ /* until the owning thread has released all */ /* of its locks. */ /* */ /* ~Lock(); Releases the lock. */ /* */ /* Example */ /* ------- */ /* */ /* TMutex LockF; */ /* */ /* void f() */ /* { */ /* TMutex::Lock lock(LockF); */ /* // critical processing goes here */ /* } */ /* */ /* Only one thread of execution will be allowed to execute the critical */ /* code inside f() at any one time. */ /* */ /*------------------------------------------------------------------------*/ class TMutex { public: #if defined( __WIN32__ ) // Windows NT enum { NoLimit = -1 }; typedef HANDLE THandle; #elif defined( __OS2__ ) // OS/2 enum { NoLimit = SEM_INDEFINITE_WAIT }; typedef HMTX THandle; #endif TMutex(); ~TMutex(); operator THandle() const; // HANDLE() under NT // HMTX() under OS/2 class Lock { public: Lock( const TMutex&, unsigned long timeOut = NoLimit ); ~Lock(); void Release(); private: const TMutex& MutexObj; }; friend Lock; private: THandle Handle; TMutex( const TMutex& ); const TMutex& operator = ( const TMutex& ); }; #if defined( __WIN32__ ) //------------------------------------------------ // // TMutex constructor // // WIN32 // inline TMutex::TMutex() { Handle = ::CreateMutex( 0, FALSE, 0 ); } //------------------------------------------------ // // TMutex destructor // // WIN32 // inline TMutex::~TMutex() { ::CloseHandle(Handle); } //------------------------------------------------ // // TMutex::operator THandle() // // WIN32 // inline TMutex::operator TMutex::THandle() const { return Handle; } //------------------------------------------------ // // TMutex::Lock constructor // // WIN32 // inline TMutex::Lock::Lock( const TMutex& mutex, unsigned long timeOut ) : MutexObj(mutex) { ::WaitForSingleObject( MutexObj, timeOut ); } //------------------------------------------------ // // TMutex::Lock destructor // // WIN32 // inline TMutex::Lock::~Lock() { Release(); } //------------------------------------------------ // // TMutex::Lock::Release() // // WIN32 // inline void TMutex::Lock::Release() { ::ReleaseMutex(MutexObj); } #elif defined( __OS2__ ) //------------------------------------------------ // // TMutex constructor // // OS/2 // inline TMutex::TMutex() { ::DosCreateMutexSem( 0, &Handle, 0, FALSE ); } //------------------------------------------------ // // TMutex destructor // // OS/2 // inline TMutex::~TMutex() { ::DosCloseMutexSem(Handle); } //------------------------------------------------ // // TMutex::operator THandle() // // OS/2 // inline TMutex::operator TMutex::THandle() const { return Handle; } //------------------------------------------------ // // TMutex::Lock constructor // // OS/2 // inline TMutex::Lock::Lock( const TMutex& mutex, unsigned long timeOut ) : MutexObj(mutex) { ::DosRequestMutexSem( MutexObj, timeOut ); } //------------------------------------------------ // // TMutex::Lock destructor // // OS/2 // inline TMutex::Lock::~Lock() { Release(); } //------------------------------------------------ // // TMutex::Lock::Release() // // OS/2 // inline void TMutex::Lock::Release() { ::DosReleaseMutexSem(MutexObj); } #endif /*------------------------------------------------------------------------*/ /* */ /* class TCriticalSection; */ /* class TCriticalSection::Lock; */ /* */ /* TCriticalSection provides a system-independent interface to critical */ /* sections in threads. With suitable underlying implementations the */ /* same code can be used under OS/2 and Windows NT. */ /* */ /* An object of type TCriticalSection can be used in conjunction with */ /* objects of type TCriticalSection::Lock to guarantee that only one */ /* thread can be executing any of the code sections protected by the */ /* lock at any given time. */ /* */ /* The differences between the classes TCriticalSection and TMutex are */ /* that a timeout can be specified when creating a Lock on a TMutex */ /* object, and that a TMutex object has a HANDLE which can be used */ /* outside the class. This mirrors the distinction made in Windows NT */ /* between a CRITICALSECTION and a Mutex. Under NT a TCriticalSection */ /* object is much faster than a TMutex object. Under operating systems */ /* that don't make this distinction a TCriticalSection object can use */ /* the same underlying implementation as a TMutex, losing the speed */ /* advantage that it has under NT. */ /* */ /* TCriticalSection Public Interface */ /* --------------------------------- */ /* */ /* TCriticalSection(); Constructor. Takes no parameters. */ /* */ /* ~TCriticalSection(); Destructor. */ /* */ /* class Lock; Handles locking and unlocking of */ /* critical sections. */ /* */ /* TCriticalSection::Lock Public Interface */ /* --------------------------------------- */ /* */ /* Lock( const TCriticalSection& ); */ /* */ /* Request a lock on the TCriticalSection */ /* object. If no Lock object in a different */ /* thread from the calling thread holds */ /* a lock on that object the lock is */ /* allowed and execution continues. If */ /* another thread holds a lock on that */ /* object the requesting thread is blocked */ /* until the owning thread has released all */ /* of its locks. */ /* */ /* ~Lock(); Releases the lock. */ /* */ /* Example */ /* ------- */ /* */ /* TCriticalSection LockF; */ /* */ /* void f() */ /* { */ /* TCriticalSection::Lock lock(LockF); */ /* // critical processing goes here */ /* } */ /* */ /* Only one thread of execution will be allowed to execute the critical */ /* code inside f() at any one time. */ /* */ /*------------------------------------------------------------------------*/ class TCriticalSection { public: TCriticalSection(); ~TCriticalSection(); class Lock { public: Lock( const TCriticalSection& ); ~Lock(); private: #if defined( __WIN32__ ) const TCriticalSection& CritSecObj; #elif defined( __OS2__ ) TMutex::Lock Lck; #endif }; friend Lock; private: #if defined( __WIN32__ ) CRITICAL_SECTION CritSec; #elif defined( __OS2__ ) TMutex CritSec; #endif TCriticalSection( const TCriticalSection& ); const TCriticalSection& operator = ( const TCriticalSection& ); }; #if defined( __WIN32__ ) //------------------------------------------------ // // TCriticalSection constructor // // WIN32 // // Use system call to initialize the CRITICAL_SECTION object. // inline TCriticalSection::TCriticalSection() { ::InitializeCriticalSection(CONST_CAST(CRITICAL_SECTION *,&CritSec)); } //------------------------------------------------ // // TCriticalSection destructor // // WIN32 // // Use system call to destroy the CRITICAL_SECTION object. // inline TCriticalSection::~TCriticalSection() { ::DeleteCriticalSection(CONST_CAST(CRITICAL_SECTION *,&CritSec)); } //------------------------------------------------ // // TCriticalSection::Lock constructor // // WIN32 // // Use system call to lock the CRITICAL_SECTION object. // inline TCriticalSection::Lock::Lock( const TCriticalSection& sec ) : CritSecObj(sec) { ::EnterCriticalSection(CONST_CAST(CRITICAL_SECTION *,&CritSecObj.CritSec)); } //------------------------------------------------ // // TCriticalSection::Lock destructor // // WIN32 // // Use system call to unlock the CRITICAL_SECTION object. // inline TCriticalSection::Lock::~Lock() { ::LeaveCriticalSection(CONST_CAST(CRITICAL_SECTION *,&CritSecObj.CritSec)); } #elif defined( __OS2__ ) //------------------------------------------------ // // TCriticalSection constructor // // OS2 // // Compiler takes care of constructing the TMutex data object. // inline TCriticalSection::TCriticalSection() { } //------------------------------------------------ // // TCriticalSection destructor // // OS2 // // Compiler takes care of destroying the TMutex data object. // inline TCriticalSection::~TCriticalSection() { } //------------------------------------------------ // // TCriticalSection::Lock constructor // // OS2 // // Construct the TMutex::Lock object to lock the // specified TCriticalSection object. // inline TCriticalSection::Lock::Lock( const TCriticalSection& sec ) : Lck(sec.CritSec) { } //------------------------------------------------ // // TCriticalSection::Lock destructor // // OS2 // // Compiler takes care of destroying the TMutex::Lock data // object, which releases the lock. // inline TCriticalSection::Lock::~Lock() { } #endif /*------------------------------------------------------------------------*/ /* */ /* class TSync; */ /* class TSync::Lock; */ /* */ /* TSync provides a system-independent interface to build classes */ /* that act like monitors, i.e., classes in which only one member */ /* can execute on a particular instance at any one time. TSync uses */ /* TCriticalSection, so it is portable to all platforms that */ /* TCriticalSection has been ported to. */ /* */ /* TSync Public Interface */ /* ------------------------- */ /* */ /* None. TSync can only be a base class. */ /* */ /* TSync Protected Interface */ /* ---------------------------- */ /* */ /* TSync( const TSync& ); */ /* Copy constructor. Does not copy the */ /* TCriticalSection object. */ /* */ /* const TSync& operator = ( const TSync& ); */ /* Assignment operator. Does not copy the */ /* TCriticalSection object. */ /* */ /* class Lock; Handles locking and unlocking of member */ /* functions. */ /* */ /* Example */ /* ------- */ /* */ /* */ /* class ThreadSafe : private TSync */ /* { */ /* public: */ /* void f(); */ /* void g(); */ /* private: */ /* int i; */ /* }; */ /* */ /* void ThreadSafe::f() */ /* { */ /* Lock lock(this); */ /* if( i == 2 ) */ /* i = 3; */ /* } */ /* */ /* void ThreadSafe::g() */ /* { */ /* Lock lock(this); */ /* if( i == 3 ) */ /* i = 2; */ /* } */ /* */ /*------------------------------------------------------------------------*/ class TSync { protected: TSync(); TSync( const TSync& ); const TSync& operator = ( const TSync& ); class Lock : private TCriticalSection::Lock { public: Lock( const TSync * ); private: static const TCriticalSection& GetRef( const TSync * ); }; friend Lock; private: TCriticalSection CritSec; }; //------------------------------------------------ // // TSync constructors // // Copy constructor does not copy the TCriticalSection object, // since the new object is not being used in any of its own // member functions. This means that the new object must start // in an unlocked state. // inline TSync::TSync() { } inline TSync::TSync( const TSync& ) { } //------------------------------------------------ // // TSync assignment operator // // Does not copy the TCriticalSection object, since the new // object is not being used in any of its own member functions. // This means that the new object must start in an unlocked state. // inline const TSync& TSync::operator = ( const TSync& ) { return *this; } //------------------------------------------------ // // TSync::Lock constructor // // Locks the TCriticalSection object in the TSync object. // inline TSync::Lock::Lock( const TSync *sync ) : TCriticalSection::Lock(GetRef(sync)) { } //------------------------------------------------ // // TSync::Lock::GetRef() // // Returns a reference to the TCriticalSection object contained // in the TSync object. // // In the diagnostic version, checks for a null pointer. // inline const TCriticalSection& TSync::Lock::GetRef( const TSync *sync ) { CHECK( sync != 0 ); return sync->CritSec; } /*------------------------------------------------------------------------*/ /* */ /* template class TStaticSync; */ /* template class TStaticSync::Lock; */ /* */ /* TStaticSync provides a system-independent interface to build sets */ /* of classes that act somewhat like monitors, i.e., classes in which */ /* only one member function can execute at any one time regardless of */ /* which instance it is being called on. TStaticSync uses */ /* TCriticalSection, so it is portable to all platforms that */ /* TCriticalSection has been ported to. */ /* */ /* TStaticSync Public Interface */ /* ------------------------- */ /* */ /* None. TStaticSync can only be a base class. */ /* */ /* TStaticSync Protected Interface */ /* ---------------------------- */ /* */ /* TStaticSync( const TStaticSync& ); */ /* Copy constructor. Does not copy the */ /* TCriticalSection object. */ /* */ /* const TStaticSync& operator = ( const TStaticSync& ); */ /* Assignment operator. Does not copy the */ /* TCriticalSection object. */ /* */ /* class Lock; Handles locking and unlocking of member */ /* functions. */ /* */ /* Example */ /* ------- */ /* */ /* */ /* class ThreadSafe : private TStaticSync */ /* { */ /* public: */ /* void f(); */ /* void g(); */ /* private: */ /* static int i; */ /* }; */ /* */ /* void ThreadSafe::f() */ /* { */ /* Lock lock; */ /* if( i == 2 ) */ /* i = 3; */ /* } */ /* */ /* void ThreadSafe::g() */ /* { */ /* Lock lock; */ /* if( i == 3 ) */ /* i = 2; */ /* } */ /* */ /*------------------------------------------------------------------------*/ template class TStaticSync { protected: TStaticSync(); TStaticSync( const TStaticSync& ); const TStaticSync& operator = ( const TStaticSync& ); ~TStaticSync(); class Lock : private TCriticalSection::Lock { public: Lock() : TCriticalSection::Lock(*TStaticSync::CritSec) {} }; friend Lock; private: static TCriticalSection *CritSec; static unsigned long Count; }; //------------------------------------------------ // // TStaticSync::CritSec // TStaticSync::Count // // Instantiate the data members. // template TCriticalSection *TStaticSync::CritSec; template unsigned long TStaticSync::Count; //------------------------------------------------ // // TStaticSync constructor // // If this is the first TStaticSync object to be constructed, // create the semaphore. // // The copy constructor only has to increment the count, since // there will already be at least one TStaticSync object, // namely, the one being copied. // template inline TStaticSync::TStaticSync() { if( Count++ == 0 ) CritSec = new TCriticalSection; } template inline TStaticSync::TStaticSync( const TStaticSync& ) { Count++; } //------------------------------------------------ // // TStaticSync assignment operator // template inline const TStaticSync& TStaticSync::operator = ( const TStaticSync& ) { return *this; } //------------------------------------------------ // // TStaticSync destructor // // If this is the only remaining TStaticSync object, // destroy the semaphore. // template inline TStaticSync::~TStaticSync() { if( --Count == 0 ) delete CritSec; } /*------------------------------------------------------------------------*/ /* */ /* class TThread; */ /* */ /* TThread provides a system-independent interface to threads. With */ /* suitable underlying implementations the same code can be used under */ /* OS/2 and Windows NT. */ /* */ /* TThread Public Interface */ /* ------------------------ */ /* */ /* Start(); Begins execution of the thread. Returns */ /* the handle of the thread. */ /* */ /* Suspend(); Suspends execution of the thread. */ /* Resume(); Resumes execution of a suspended thread. */ /* */ /* Terminate(); Sets an internal flag that indicates */ /* that the thread should exit. The */ /* derived class can check the state of */ /* this flag by calling ShouldTerminate(). */ /* */ /* WaitForExit( unsigned long timeout = NoLimit ); */ /* Blocks the calling thread until the */ /* internal thread exits or until the time */ /* specified by timeout, in milliseconds, */ /* expires. A timeout of NoLimit says to */ /* wait indefinitely. */ /* */ /* TerminateAndWait( unsigned long timeout = NoLimit ); */ /* Combines the behavior of Terminate() and */ /* WaitForExit(). Sets an internal flag that */ /* indicates that the thread should exit */ /* and blocks the calling thread until the */ /* internal thread exits or until the time */ /* specified by timeout, in milliseconds, */ /* expires. A timeout of NoLimit says to */ /* wait indefinitely. */ /* */ /* GetStatus(); Gets the current status of the thread. */ /* See TThread::Status for possible values. */ /* */ /* GetPriority(); Gets the priority of the thread. */ /* SetPriority(); Sets the priority of the thread. */ /* */ /* enum Status; Identifies the states that the class */ /* can be in. */ /* */ /* Created The class has been created but the */ /* thread has not been started. */ /* Running The thread is running. */ /* */ /* Suspended The thread has been suspended. */ /* */ /* Finished The thread has finished execution. */ /* */ /* Invalid The object is invalid. Currently this */ /* happens only when the operating system */ /* is unable to start the thread. */ /* */ /* class ThreadError; The error class that defines the objects */ /* that are thrown when an error occurs. */ /* */ /* TThread::ThreadError Public Interface */ /* ------------------------------------- */ /* */ /* enum ErrorType; Identifies the type of error that */ /* occurred. */ /* */ /* SuspendBeforeRun The user called Suspend() on an object */ /* before calling Start(). */ /* */ /* ResumeBeforeRun The user called Resume() on an object */ /* before calling Start(). */ /* */ /* ResumeDuringRun The user called Resume() on a thread that */ /* was not Suspended. */ /* */ /* SuspendAfterExit The user called Suspend() on an object */ /* whose thread had already exited. */ /* */ /* ResumeAfterExit The user called Resume() on an object */ /* whose thread had already exited. */ /* */ /* CreationFailure The operating system was unable to create */ /* the thread. */ /* */ /* DestroyBeforeExit The object's destructor was invoked */ /* its thread had exited. */ /* */ /* AssignError An attempt was made to assign to an */ /* object that was not in either the */ /* Created or the Finished state. */ /* */ /* ErrorType GetErrorType() const; */ /* Returns a code indicating the type of */ /* error that occurred. */ /* */ /* string why(); Returns a string that describes the */ /* error. Inherited from xmsg. */ /* */ /* TThread Protected Interface */ /* --------------------------- */ /* */ /* TThread(); Creates an object of type TThread. */ /* virtual ~TThread(); Destroys the object. */ /* */ /* const TThread& operator = ( const TThread& ); */ /* The target object must be in either the */ /* Created state or the Finished state. If */ /* so, puts the object into the Created */ /* state. If the object is not in either the */ /* Created state or the Finished state it */ /* is an error and an exception will be */ /* thrown. */ /* */ /* TThread( const TThread& ); */ /* Pts the object into the Created */ /* state, just like the default constructor. */ /* Does not copy any of the internal details */ /* of the thread being copied. */ /* */ /* virtual unsigned long Run() = 0; */ /* The function that does the work. Calling */ /* Start() creates a thread that begins */ /* executing Run() with the 'this' pointer */ /* pointing to the TThread-based object. */ /* */ /* int ShouldTerminate() const; */ /* Returns a non-zero value to indicate */ /* that Terminate() or TerminateAndWait() */ /* has been called. If this capability is */ /* being used, the thread should call */ /* ShouldTerminate() regularly, and if it */ /* returns a non-zero value the thread */ /* finish its processing and exit. */ /* */ /* Example */ /* ------- */ /* */ /* class TimerThread : public TThread */ /* { */ /* public: */ /* TimerThread() : Count(0) {} */ /* private: */ /* unsigned long Run(); */ /* int Count; */ /* }; */ /* */ /* unsigned long TimerThread::Run() */ /* { */ /* // loop 10 times */ /* while( Count++ < 10 ) */ /* { */ /* Sleep(1000); // delay 1 second */ /* cout << "Iteration " << Count << endl; */ /* } */ /* return 0L; */ /* } */ /* */ /* int main() */ /* { */ /* TimerThread timer; */ /* timer.Start(); */ /* Sleep( 20000 ); // delay 20 seconds */ /* return 0; */ /* } */ /* */ /* Internal States */ /* --------------- */ /* */ /* Created : the object has been created but its thread has not been */ /* started. The only valid transition from this state is */ /* to Running, which happens on a call to Start(). In */ /* particular, a call to Suspend() or Resume() when the */ /* object is in this state is an error and will throw an */ /* exception. */ /* */ /* Running: the thread has been started successfully. There are two */ /* transitions from this state: */ /* */ /* When the user calls Suspend() the object moves into */ /* the Suspended state. */ /* */ /* When the thread exits the object moves into the */ /* Finished state. */ /* */ /* Calling Resume() on an object that is in the Running */ /* state is an error and will throw an exception. */ /* */ /* Suspended: the thread has been suspended by the user. Subsequent */ /* calls to Suspend() nest, so there must be as many calls */ /* to Resume() as there were to Suspend() before the thread */ /* actually resumes execution. */ /* */ /* Finished: the thread has finished executing. There are no valid */ /* transitions out of this state. This is the only state */ /* from which it is legal to invoke the destructor for the */ /* object. Invoking the destructor when the object is in */ /* any other state is an error and will throw an exception. */ /* */ /*------------------------------------------------------------------------*/ class _BIDSCLASS TThread { public: #if defined( __WIN32__ ) // Windows NT enum { NoLimit = -1 }; typedef HANDLE THandle; #elif defined( __OS2__ ) // OS/2 enum { NoLimit = DCWW_WAIT }; typedef TID THandle; #endif enum Status { Created, Running, Suspended, Finished, Invalid }; THandle Start(); unsigned long Suspend(); unsigned long Resume(); void Terminate(); unsigned long WaitForExit( unsigned long timeout = NoLimit ); unsigned long TerminateAndWait( unsigned long timeout = NoLimit ); Status GetStatus() const; int GetPriority() const; int SetPriority(int); class ThreadError : public xmsg { friend TThread; public: enum ErrorType { SuspendBeforeRun, ResumeBeforeRun, ResumeDuringRun, SuspendAfterExit, ResumeAfterExit, CreationFailure, DestroyBeforeExit, AssignError }; ErrorType GetErrorType() const; private: ThreadError(ErrorType type); static string MakeString(ErrorType type ); ErrorType Type; }; protected: TThread(); // Copying a thread puts the target into the Created state TThread( const TThread& ); const TThread& operator = ( const TThread& ); virtual ~TThread(); int ShouldTerminate() const; private: virtual unsigned long Run() = 0; Status CheckStatus() const; THandle Handle; #if defined( __MT__ ) static void _USERENTRY Execute( void *thread ); #elif defined( __WIN32__ ) static unsigned long _stdcall Execute( void *thread ); #else static void __stdcall Execute( unsigned long ); #endif #if defined( __WIN32__ ) DWORD ThreadId; #else ULONG Priority; #endif mutable Status Stat; int TerminationRequested; }; //------------------------------------------------ // // TThread::GetStatus() // // If the thread is marked as Running it may have terminated // without our knowing it, so we have to check. // #if defined( BI_NO_MUTABLE ) inline TThread::Status TThread::GetStatus() const { if( Stat == Running ) CONST_CAST(TThread *,this)->Stat = CheckStatus(); return Stat; } #else inline TThread::Status TThread::GetStatus() const { if( Stat == Running ) Stat = CheckStatus(); return Stat; } #endif //------------------------------------------------ // // TThread::GetPriority() // // Direct OS call under WIN32. Return stored value under OS/2. // inline int TThread::GetPriority() const { #if defined( __WIN32__ ) return ::GetThreadPriority(Handle); #else return Priority; #endif } //------------------------------------------------ // // TThread::ShouldTerminate() // inline int TThread::ShouldTerminate() const { return TerminationRequested; } //------------------------------------------------ // // TThread::ThreadError::GetErrorType() // inline TThread::ThreadError::ErrorType TThread::ThreadError::GetErrorType() const { return Type; } #if defined( BI_CLASSLIB_NO_po ) #pragma option -po. #endif #endif // __THREAD_H