1 // Created on: 2006-04-12
2 // Created by: Andrey BETENEV
3 // Copyright (c) 2006-2014 OPEN CASCADE SAS
5 // This file is part of Open CASCADE Technology software library.
7 // This library is free software; you can redistribute it and/or modify it under
8 // the terms of the GNU Lesser General Public License version 2.1 as published
9 // by the Free Software Foundation, with special exception defined in the file
10 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
11 // distribution for complete text of the license and disclaimer of any warranty.
13 // Alternatively, this file may be used under the terms of Open CASCADE
14 // commercial license or contractual agreement.
16 #include <OSD_Thread.hxx>
18 //=============================================
19 // OSD_Thread::OSD_Thread
20 //=============================================
21 OSD_Thread::OSD_Thread ()
22 : myFunc(0), myThread(0), myThreadId(0), myPriority(0)
25 //=============================================
26 // OSD_Thread::OSD_Thread
27 //=============================================
29 OSD_Thread::OSD_Thread (const OSD_ThreadFunction &func)
30 : myFunc(func), myThread(0), myThreadId(0), myPriority(0)
33 //=============================================
34 // OSD_Thread::OSD_Thread
35 //=============================================
37 OSD_Thread::OSD_Thread (const OSD_Thread &other)
38 : myFunc(other.myFunc), myThread(0), myThreadId(0)
43 //=============================================
45 //=============================================
47 void OSD_Thread::Assign (const OSD_Thread &other)
49 // copy function pointer
50 myFunc = other.myFunc;
51 myPriority = other.myPriority;
53 // detach current thread
57 // duplicate the source handle
58 if ( other.myThread ) {
59 HANDLE hProc = GetCurrentProcess(); // we are always within the same process
60 DuplicateHandle ( hProc, other.myThread, hProc, &myThread,
61 0, TRUE, DUPLICATE_SAME_ACCESS );
64 // On Unix/Linux, just copy the thread id
65 myThread = other.myThread;
68 myThreadId = other.myThreadId;
71 //=============================================
72 // OSD_Thread::~OSD_Thread
73 //=============================================
75 OSD_Thread::~OSD_Thread()
80 //=============================================
81 //function : SetPriority
82 //purpose : Set the thread priority relative to the caller's priority
83 //=============================================
85 void OSD_Thread::SetPriority (const Standard_Integer thePriority)
87 myPriority = thePriority;
90 SetThreadPriority (myThread, thePriority);
94 //=============================================
95 // OSD_Thread::SetFunction
96 //=============================================
98 void OSD_Thread::SetFunction (const OSD_ThreadFunction &func)
100 // close current handle if any
105 //=============================================
107 //=============================================
111 // On Windows the signature of the thread function differs from that on UNIX/Linux.
112 // As we use the same definition of the thread function on all platforms (POSIX-like),
113 // we need to introduce appropriate wrapper function on Windows.
114 struct WNTthread_data { void *data; OSD_ThreadFunction func; };
115 static DWORD WINAPI WNTthread_func (LPVOID data)
117 WNTthread_data *adata = (WNTthread_data*)data;
118 void* ret = adata->func ( adata->data );
120 return PtrToLong (ret);
124 Standard_Boolean OSD_Thread::Run (const Standard_Address data,
126 const Standard_Integer WNTStackSize
128 const Standard_Integer
132 if ( ! myFunc ) return Standard_False;
134 // detach current thread, if open
139 // allocate intermediate data structure to pass both data parameter and address
140 // of the real thread function to Windows thread wrapper function
141 WNTthread_data *adata = (WNTthread_data*)malloc ( sizeof(WNTthread_data) );
142 if ( ! adata ) return Standard_False;
144 adata->func = myFunc;
146 // then try to create a new thread
147 DWORD aThreadId = DWORD();
148 myThread = CreateThread ( NULL, WNTStackSize, WNTthread_func,
149 adata, 0, &aThreadId );
150 myThreadId = aThreadId;
152 SetThreadPriority (myThread, myPriority);
154 memset ( adata, 0, sizeof(WNTthread_data) );
160 if (pthread_create (&myThread, 0, myFunc, data) != 0)
166 myThreadId = (Standard_ThreadId)myThread;
169 return myThread != 0;
172 //=============================================
173 // OSD_Thread::Detach
174 //=============================================
176 void OSD_Thread::Detach ()
180 // On Windows, close current handle
182 CloseHandle ( myThread );
186 // On Unix/Linux, detach a thread
188 pthread_detach ( myThread );
196 //=============================================
198 //=============================================
200 Standard_Boolean OSD_Thread::Wait (Standard_Address& theResult)
202 // check that thread handle is not null
206 return Standard_False;
210 // On Windows, wait for the thread handle to be signaled
211 if (WaitForSingleObject (myThread, INFINITE) != WAIT_OBJECT_0)
213 return Standard_False;
216 // and convert result of the thread execution to Standard_Address
218 if (GetExitCodeThread (myThread, &anExitCode))
220 theResult = ULongToPtr (anExitCode);
223 CloseHandle (myThread);
226 return Standard_True;
228 // On Unix/Linux, join the thread
229 if (pthread_join (myThread, &theResult) != 0)
231 return Standard_False;
236 return Standard_True;
240 //=============================================
242 //=============================================
244 Standard_Boolean OSD_Thread::Wait (const Standard_Integer theTimeMs,
245 Standard_Address& theResult)
247 // check that thread handle is not null
251 return Standard_False;
255 // On Windows, wait for the thread handle to be signaled
256 DWORD ret = WaitForSingleObject (myThread, theTimeMs);
257 if (ret == WAIT_OBJECT_0)
260 if (GetExitCodeThread (myThread, &anExitCode))
262 theResult = ULongToPtr (anExitCode);
265 CloseHandle (myThread);
268 return Standard_True;
270 else if (ret == WAIT_TIMEOUT)
272 return Standard_False;
275 return Standard_False;
277 #if defined(__GLIBC__) && defined(__GLIBC_PREREQ)
278 #if __GLIBC_PREREQ(2,4)
284 struct timespec aTimeout;
285 if (clock_gettime (CLOCK_REALTIME, &aTimeout) == -1)
287 return Standard_False;
290 time_t aSeconds = (theTimeMs / 1000);
291 long aMicroseconds = (theTimeMs - aSeconds * 1000) * 1000;
292 aTimeout.tv_sec += aSeconds;
293 aTimeout.tv_nsec += aMicroseconds * 1000;
295 if (pthread_timedjoin_np (myThread, &theResult, &aTimeout) != 0)
297 return Standard_False;
301 // join the thread without timeout
303 if (pthread_join (myThread, &theResult) != 0)
305 return Standard_False;
310 return Standard_True;
314 //=============================================
316 //=============================================
318 Standard_ThreadId OSD_Thread::GetId () const
323 //=============================================
324 // OSD_Thread::Current
325 //=============================================
327 Standard_ThreadId OSD_Thread::Current ()
330 return GetCurrentThreadId();
332 return (Standard_ThreadId)pthread_self();