0022972: Eliminate macro definitions that has compiler-provided analogs (WNT and...
[occt.git] / src / OSD / OSD_Thread.cxx
CommitLineData
b311480e 1// Created on: 2006-04-12
2// Created by: Andrey BETENEV
973c2be1 3// Copyright (c) 2006-2014 OPEN CASCADE SAS
b311480e 4//
973c2be1 5// This file is part of Open CASCADE Technology software library.
b311480e 6//
d5f74e42 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
973c2be1 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.
b311480e 12//
973c2be1 13// Alternatively, this file may be used under the terms of Open CASCADE
14// commercial license or contractual agreement.
7fd59977 15
42cf5bc1 16
17#include <OSD_Thread.hxx>
7fd59977 18
19//=============================================
20// OSD_Thread::OSD_Thread
21//=============================================
7fd59977 22OSD_Thread::OSD_Thread ()
23 : myFunc(0), myThread(0), myThreadId(0), myPriority(0)
24{}
25
26//=============================================
27// OSD_Thread::OSD_Thread
28//=============================================
29
30OSD_Thread::OSD_Thread (const OSD_ThreadFunction &func)
31 : myFunc(func), myThread(0), myThreadId(0), myPriority(0)
32{}
33
34//=============================================
35// OSD_Thread::OSD_Thread
36//=============================================
37
38OSD_Thread::OSD_Thread (const OSD_Thread &other)
39 : myFunc(other.myFunc), myThread(0), myThreadId(0)
40{
41 Assign ( other );
42}
43
44//=============================================
45// OSD_Thread::Assign
46//=============================================
47
48void OSD_Thread::Assign (const OSD_Thread &other)
49{
50 // copy function pointer
51 myFunc = other.myFunc;
52 myPriority = other.myPriority;
53
57c28b61 54#ifdef _WIN32
7fd59977 55
56 // On Windows, close current handle
57 if ( myThread )
58 CloseHandle ( myThread );
59 myThread = 0;
60
61 // and replace it by duplicate of the source handle
62 if ( other.myThread ) {
63 HANDLE hProc = GetCurrentProcess(); // we are always within the same process
64 DuplicateHandle ( hProc, other.myThread, hProc, &myThread,
65 0, TRUE, DUPLICATE_SAME_ACCESS );
66 }
67
68#else
69
70 // On Unix/Linux, just copy the thread id
71 myThread = other.myThread;
72
73#endif
74
75 myThreadId = other.myThreadId;
76}
77
78//=============================================
79// OSD_Thread::Destroy
80//=============================================
81
82void OSD_Thread::Destroy ()
83{
57c28b61 84#ifdef _WIN32
7fd59977 85
86 // On Windows, close current handle
87 if ( myThread )
88 CloseHandle ( myThread );
89
90#else
91
92 // On Unix/Linux, do nothing
93
94#endif
95
96 myThread = 0;
97 myThreadId = 0;
98}
99
100//=============================================
101//function : SetPriority
102//purpose : Set the thread priority relative to the caller's priority
103//=============================================
104
105void OSD_Thread::SetPriority (const Standard_Integer thePriority)
106{
107 myPriority = thePriority;
57c28b61 108#ifdef _WIN32
7fd59977 109 if (myThread)
110 SetThreadPriority (myThread, thePriority);
111#endif
112}
113
114//=============================================
115// OSD_Thread::SetFunction
116//=============================================
117
118void OSD_Thread::SetFunction (const OSD_ThreadFunction &func)
119{
120 // close current handle if any
121 Destroy();
122 myFunc = func;
123}
124
125//=============================================
126// OSD_Thread::Run
127//=============================================
128
57c28b61 129#ifdef _WIN32
7fd59977 130#include <malloc.h>
131// On Windows the signature of the thread function differs from that on UNIX/Linux.
132// As we use the same definition of the thread function on all platforms (POSIX-like),
133// we need to introduce appropriate wrapper function on Windows.
134struct WNTthread_data { void *data; OSD_ThreadFunction func; };
135static DWORD WINAPI WNTthread_func (LPVOID data)
136{
137 WNTthread_data *adata = (WNTthread_data*)data;
138 void* ret = adata->func ( adata->data );
139 free ( adata );
140 return (DWORD)ret;
141}
142#endif
143
144Standard_Boolean OSD_Thread::Run (const Standard_Address data,
57c28b61 145#ifdef _WIN32
7fd59977 146 const Standard_Integer WNTStackSize
147#else
148 const Standard_Integer
149#endif
150 )
151{
152 if ( ! myFunc ) return Standard_False;
153
154 myThreadId = 0;
155
57c28b61 156#ifdef _WIN32
7fd59977 157
158 // On Windows, close current handle if open
159 if ( myThread )
160 CloseHandle ( myThread );
161 myThread = 0;
162
163 // allocate intermediate data structure to pass both data parameter and address
164 // of the real thread function to Windows thread wrapper function
165 WNTthread_data *adata = (WNTthread_data*)malloc ( sizeof(WNTthread_data) );
166 if ( ! adata ) return Standard_False;
167 adata->data = data;
168 adata->func = myFunc;
169
170 // then try to create a new thread
171
172 myThread = CreateThread ( NULL, WNTStackSize, WNTthread_func,
173 adata, 0, &myThreadId );
174 if ( myThread )
175 SetThreadPriority (myThread, myPriority);
176 else {
177 memset ( adata, 0, sizeof(WNTthread_data) );
178 free ( adata );
179 }
180
181#else
182
183 // On Unix/Linux, create a new thread
184 if ( pthread_create ( &myThread, 0, myFunc, data ) )
185 myThread = 0;
186 else myThreadId = myThread;
187
188#endif
189 return myThread != 0;
190}
191
192//=============================================
193// OSD_Thread::Detach
194//=============================================
195
196void OSD_Thread::Detach ()
197{
57c28b61 198#ifdef _WIN32
7fd59977 199
200 // On Windows, close current handle
201 if ( myThread )
202 CloseHandle ( myThread );
203
204#else
205
206 // On Unix/Linux, detach a thread
207 if ( myThread )
208 pthread_detach ( myThread );
209
210#endif
211
212 myThread = 0;
213 myThreadId = 0;
214}
215
216//=============================================
217// OSD_Thread::Wait
218//=============================================
219
220Standard_Boolean OSD_Thread::Wait () const
221{
222 Standard_Address aRes = 0;
223 return Wait ( aRes );
224}
225
226//=============================================
227// OSD_Thread::Wait
228//=============================================
229
230Standard_Boolean OSD_Thread::Wait (Standard_Address &result) const
231{
232 // check that thread handle is not null
233 result = 0;
234 if ( ! myThread )
235 return Standard_False;
236
57c28b61 237#ifdef _WIN32
7fd59977 238
239 // On Windows, wait for the thread handle to be signaled
240 if ( WaitForSingleObject ( myThread, INFINITE ) != WAIT_OBJECT_0 )
241 return Standard_False;
242
243 // and convert result of the thread execution to Standard_Address
244 DWORD anExitCode;
245 if ( GetExitCodeThread ( myThread, &anExitCode ) )
246 result = (Standard_Address)anExitCode;
247 return Standard_True;
248
249#else
250
251 // On Unix/Linux, join the thread
252 return ! pthread_join ( myThread, &result );
253
254#endif
255}
256
257//=============================================
258// OSD_Thread::Wait
259//=============================================
260
261Standard_Boolean OSD_Thread::Wait (const Standard_Integer time, Standard_Address &result) const
262{
263 // check that thread handle is not null
264 result = 0;
265 if ( ! myThread )
266 return Standard_False;
267
57c28b61 268#ifdef _WIN32
7fd59977 269
270 // On Windows, wait for the thread handle to be signaled
271 DWORD ret = WaitForSingleObject ( myThread, time );
272 if (ret == WAIT_OBJECT_0)
273 {
274 DWORD anExitCode;
275 if ( GetExitCodeThread ( myThread, &anExitCode ) )
276 result = (Standard_Address)anExitCode;
277 return Standard_True;
278 }
279 else if (ret == WAIT_TIMEOUT)
280 {
281 return Standard_False;
282 }
283
284 return Standard_False;
285
286#else
287
288 // On Unix/Linux, join the thread
289 return ! pthread_join ( myThread, &result );
290
291#endif
292}
293
294//=============================================
295// OSD_Thread::GetId
296//=============================================
297
298Standard_ThreadId OSD_Thread::GetId () const
299{
300 return myThreadId;
301}
302
303//=============================================
304// OSD_Thread::Current
305//=============================================
306
307Standard_ThreadId OSD_Thread::Current ()
308{
57c28b61 309#ifdef _WIN32
7fd59977 310 return GetCurrentThreadId();
311#else
312 return pthread_self();
313#endif
314}
315