diff --git a/src/OSD/OSD_Thread.cxx b/src/OSD/OSD_Thread.cxx index 95097687c6..6cb971632e 100644 --- a/src/OSD/OSD_Thread.cxx +++ b/src/OSD/OSD_Thread.cxx @@ -13,7 +13,6 @@ // Alternatively, this file may be used under the terms of Open CASCADE // commercial license or contractual agreement. - #include //============================================= @@ -47,54 +46,35 @@ OSD_Thread::OSD_Thread (const OSD_Thread &other) void OSD_Thread::Assign (const OSD_Thread &other) { - // copy function pointer + // copy function pointer myFunc = other.myFunc; myPriority = other.myPriority; + // detach current thread + Detach(); + #ifdef _WIN32 - - // On Windows, close current handle - if ( myThread ) - CloseHandle ( myThread ); - myThread = 0; - - // and replace it by duplicate of the source handle + // duplicate the source handle if ( other.myThread ) { HANDLE hProc = GetCurrentProcess(); // we are always within the same process DuplicateHandle ( hProc, other.myThread, hProc, &myThread, 0, TRUE, DUPLICATE_SAME_ACCESS ); } - #else - // On Unix/Linux, just copy the thread id myThread = other.myThread; - -#endif +#endif myThreadId = other.myThreadId; } //============================================= -// OSD_Thread::Destroy +// OSD_Thread::~OSD_Thread //============================================= -void OSD_Thread::Destroy () +OSD_Thread::~OSD_Thread() { -#ifdef _WIN32 - - // On Windows, close current handle - if ( myThread ) - CloseHandle ( myThread ); - -#else - - // On Unix/Linux, do nothing - -#endif - - myThread = 0; - myThreadId = 0; + Detach(); } //============================================= @@ -118,7 +98,7 @@ void OSD_Thread::SetPriority (const Standard_Integer thePriority) void OSD_Thread::SetFunction (const OSD_ThreadFunction &func) { // close current handle if any - Destroy(); + Detach(); myFunc = func; } @@ -141,7 +121,7 @@ static DWORD WINAPI WNTthread_func (LPVOID data) } #endif -Standard_Boolean OSD_Thread::Run (const Standard_Address data, +Standard_Boolean OSD_Thread::Run (const Standard_Address data, #ifdef _WIN32 const Standard_Integer WNTStackSize #else @@ -151,15 +131,11 @@ Standard_Boolean OSD_Thread::Run (const Standard_Address data, { if ( ! myFunc ) return Standard_False; - myThreadId = 0; + // detach current thread, if open + Detach(); #ifdef _WIN32 - // On Windows, close current handle if open - if ( myThread ) - CloseHandle ( myThread ); - myThread = 0; - // allocate intermediate data structure to pass both data parameter and address // of the real thread function to Windows thread wrapper function WNTthread_data *adata = (WNTthread_data*)malloc ( sizeof(WNTthread_data) ); @@ -167,8 +143,8 @@ Standard_Boolean OSD_Thread::Run (const Standard_Address data, adata->data = data; adata->func = myFunc; - // then try to create a new thread - + // then try to create a new thread + myThread = CreateThread ( NULL, WNTStackSize, WNTthread_func, adata, 0, &myThreadId ); if ( myThread ) @@ -180,12 +156,15 @@ Standard_Boolean OSD_Thread::Run (const Standard_Address data, #else - // On Unix/Linux, create a new thread - if ( pthread_create ( &myThread, 0, myFunc, data ) ) + if (pthread_create (&myThread, 0, myFunc, data) != 0) + { myThread = 0; - else myThreadId = myThread; - -#endif + } + else + { + myThreadId = myThread; + } +#endif return myThread != 0; } @@ -197,17 +176,17 @@ void OSD_Thread::Detach () { #ifdef _WIN32 - // On Windows, close current handle - if ( myThread ) + // On Windows, close current handle + if ( myThread ) CloseHandle ( myThread ); #else // On Unix/Linux, detach a thread - if ( myThread ) + if ( myThread ) pthread_detach ( myThread ); -#endif +#endif myThread = 0; myThreadId = 0; @@ -217,63 +196,74 @@ void OSD_Thread::Detach () // OSD_Thread::Wait //============================================= -Standard_Boolean OSD_Thread::Wait () const -{ - Standard_Address aRes = 0; - return Wait ( aRes ); -} - -//============================================= -// OSD_Thread::Wait -//============================================= - -Standard_Boolean OSD_Thread::Wait (Standard_Address &result) const +Standard_Boolean OSD_Thread::Wait (Standard_Address& theResult) { // check that thread handle is not null - result = 0; - if ( ! myThread ) + theResult = 0; + if (!myThread) + { return Standard_False; + } #ifdef _WIN32 - // On Windows, wait for the thread handle to be signaled - if ( WaitForSingleObject ( myThread, INFINITE ) != WAIT_OBJECT_0 ) + if (WaitForSingleObject (myThread, INFINITE) != WAIT_OBJECT_0) + { return Standard_False; + } // and convert result of the thread execution to Standard_Address DWORD anExitCode; - if ( GetExitCodeThread ( myThread, &anExitCode ) ) - result = ULongToPtr (anExitCode); + if (GetExitCodeThread (myThread, &anExitCode)) + { + theResult = ULongToPtr (anExitCode); + } + + CloseHandle (myThread); + myThread = 0; + myThreadId = 0; return Standard_True; - #else - // On Unix/Linux, join the thread - return ! pthread_join ( myThread, &result ); + if (pthread_join (myThread, &theResult) != 0) + { + return Standard_False; + } -#endif + myThread = 0; + myThreadId = 0; + return Standard_True; +#endif } //============================================= // OSD_Thread::Wait //============================================= -Standard_Boolean OSD_Thread::Wait (const Standard_Integer theTimeMs, Standard_Address &result) const +Standard_Boolean OSD_Thread::Wait (const Standard_Integer theTimeMs, + Standard_Address& theResult) { // check that thread handle is not null - result = 0; - if ( ! myThread ) + theResult = 0; + if (!myThread) + { return Standard_False; + } #ifdef _WIN32 - // On Windows, wait for the thread handle to be signaled DWORD ret = WaitForSingleObject (myThread, theTimeMs); if (ret == WAIT_OBJECT_0) { DWORD anExitCode; - if ( GetExitCodeThread ( myThread, &anExitCode ) ) - result = ULongToPtr (anExitCode); + if (GetExitCodeThread (myThread, &anExitCode)) + { + theResult = ULongToPtr (anExitCode); + } + + CloseHandle (myThread); + myThread = 0; + myThreadId = 0; return Standard_True; } else if (ret == WAIT_TIMEOUT) @@ -282,7 +272,6 @@ Standard_Boolean OSD_Thread::Wait (const Standard_Integer theTimeMs, Standard_Ad } return Standard_False; - #else #if defined(__GLIBC__) && defined(__GLIBC_PREREQ) #if __GLIBC_PREREQ(2,4) @@ -302,13 +291,22 @@ Standard_Boolean OSD_Thread::Wait (const Standard_Integer theTimeMs, Standard_Ad aTimeout.tv_sec += aSeconds; aTimeout.tv_nsec += aMicroseconds * 1000; - return pthread_timedjoin_np (myThread, &result, &aTimeout) == 0; + if (pthread_timedjoin_np (myThread, &theResult, &aTimeout) != 0) + { + return Standard_False; + } + #else // join the thread without timeout (void )theTimeMs; - return pthread_join (myThread, &result) == 0; + if (pthread_join (myThread, &theResult) != 0) + { + return Standard_False; + } #endif - + myThread = 0; + myThreadId = 0; + return Standard_True; #endif } @@ -325,12 +323,11 @@ Standard_ThreadId OSD_Thread::GetId () const // OSD_Thread::Current //============================================= -Standard_ThreadId OSD_Thread::Current () +Standard_ThreadId OSD_Thread::Current () { #ifdef _WIN32 return GetCurrentThreadId(); #else return pthread_self(); -#endif +#endif } - diff --git a/src/OSD/OSD_Thread.hxx b/src/OSD/OSD_Thread.hxx index f74cbe6cab..527f440594 100644 --- a/src/OSD/OSD_Thread.hxx +++ b/src/OSD/OSD_Thread.hxx @@ -30,49 +30,43 @@ //! A simple platform-intependent interface to execute //! and control threads. -class OSD_Thread +class OSD_Thread { public: DEFINE_STANDARD_ALLOC - //! Empty constructor Standard_EXPORT OSD_Thread(); - + //! Initialize the tool by the thread function //! //! Note: On Windows, you might have to take an address of the thread //! function explicitly to pass it to this constructor without compiler error Standard_EXPORT OSD_Thread(const OSD_ThreadFunction& func); - + //! Copy constructor Standard_EXPORT OSD_Thread(const OSD_Thread& other); - + //! Copy thread handle from other OSD_Thread object. Standard_EXPORT void Assign (const OSD_Thread& other); void operator = (const OSD_Thread& other) { Assign(other); } - - //! Destructor. On Windows, closes handle to the thread. - //! On UNIX/Linux, does nothing. - Standard_EXPORT void Destroy(); -~OSD_Thread() -{ - Destroy(); -} - + + //! Destructor. Detaches the thread if it wasn't done already. + Standard_EXPORT ~OSD_Thread(); + Standard_EXPORT void SetPriority (const Standard_Integer thePriority); - + //! Initialize the tool by the thread function. //! If the current thread handle is not null, nullifies it. //! //! Note: On Windows, you might have to take an address of the thread //! function explicitly to pass it to this method without compiler error Standard_EXPORT void SetFunction (const OSD_ThreadFunction& func); - + //! Starts a thread with thread function given in constructor, //! passing the specified input data (as void *) to it. //! The parameter \a WNTStackSize (on Windows only) @@ -80,7 +74,7 @@ void operator = (const OSD_Thread& other) //! (by default - the same as for the current executable). //! Returns True if thread started successfully Standard_EXPORT Standard_Boolean Run (const Standard_Address data = 0, const Standard_Integer WNTStackSize = 0); - + //! Detaches the execution thread from this Thread object, //! so that it cannot be waited. //! Note that mechanics of this operation is different on @@ -89,9 +83,14 @@ void operator = (const OSD_Thread& other) //! However, the purpose is the same: to instruct the system to //! release all thread data upon its completion. Standard_EXPORT void Detach(); - - Standard_EXPORT Standard_Boolean Wait() const; - + + //! Waits till the thread finishes execution. + Standard_Boolean Wait() + { + Standard_Address aRes = 0; + return Wait (aRes); + } + //! Wait till the thread finishes execution. //! Returns True if wait was successful, False in case of error. //! @@ -101,45 +100,27 @@ void operator = (const OSD_Thread& other) //! Note however that it is advisable not to rely upon returned result //! value, as it is not always the value actually returned by the thread //! function. In addition, on Windows it is converted via DWORD. - Standard_EXPORT Standard_Boolean Wait (Standard_Address& result) const; - + Standard_EXPORT Standard_Boolean Wait (Standard_Address& theResult); + //! Waits for some time and if the thread is finished, //! it returns the result. //! The function returns false if the thread is not finished yet. - Standard_EXPORT Standard_Boolean Wait (const Standard_Integer time, Standard_Address& result) const; - + Standard_EXPORT Standard_Boolean Wait (const Standard_Integer time, Standard_Address& theResult); + //! Returns ID of the currently controlled thread ID, //! or 0 if no thread is run Standard_EXPORT Standard_ThreadId GetId() const; - + //! Auxiliary: returns ID of the current thread Standard_EXPORT static Standard_ThreadId Current(); - - - -protected: - - - - - private: - - OSD_ThreadFunction myFunc; OSD_PThread myThread; Standard_ThreadId myThreadId; Standard_Integer myPriority; - }; - - - - - - #endif // _OSD_Thread_HeaderFile