CreateThreadEx/WCE fixed
[public/netxms.git] / include / nms_threads.h
CommitLineData
54481027 1/*
4997be5c 2** NetXMS - Network Management System
54481027
VK
3** Copyright (C) 2003 Victor Kirhenshtein
4**
5** This program is free software; you can redistribute it and/or modify
6** it under the terms of the GNU General Public License as published by
7** the Free Software Foundation; either version 2 of the License, or
8** (at your option) any later version.
9**
10** This program is distributed in the hope that it will be useful,
11** but WITHOUT ANY WARRANTY; without even the implied warranty of
12** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13** GNU General Public License for more details.
14**
15** You should have received a copy of the GNU General Public License
16** along with this program; if not, write to the Free Software
17** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18**
19** $module: nms_threads.h
20**
21**/
22
23#ifndef _nms_threads_h_
24#define _nms_threads_h_
25
26#ifdef _WIN32
27
018fda4d
AK
28#ifndef UNDER_CE
29# include <process.h>
30#endif
54481027
VK
31
32//
33// Related datatypes and constants
34//
35
36#define MUTEX HANDLE
37#define THREAD HANDLE
38#define CONDITION HANDLE
39
449e3da9
VK
40#define INVALID_MUTEX_HANDLE INVALID_HANDLE_VALUE
41#define INVALID_CONDITION_HANDLE INVALID_HANDLE_VALUE
ccdbbb52
VK
42#define INVALID_THREAD_HANDLE (NULL)
43
44typedef unsigned int THREAD_RESULT;
45
46#define THREAD_OK 0
47#define THREAD_CALL __stdcall
54481027
VK
48
49
50//
51// Inline functions
52//
53
54inline void ThreadSleep(int iSeconds)
55{
56 Sleep((DWORD)iSeconds * 1000); // Convert to milliseconds
57}
58
59inline void ThreadSleepMs(DWORD dwMilliseconds)
60{
61 Sleep(dwMilliseconds);
62}
63
ccdbbb52 64inline BOOL ThreadCreate(THREAD_RESULT (THREAD_CALL *start_address )(void *), int stack_size, void *args)
54481027 65{
ccdbbb52
VK
66 HANDLE hThread;
67 unsigned int dwThreadId;
68
f2fdf1b5 69#ifdef UNDER_CE
631ec742
AK
70 hThread = CreateThread(NULL, (DWORD)stack_size, (LPTHREAD_START_ROUTINE)start_address,
71 args, 0, (LPDWORD)&dwThreadId);
f2fdf1b5 72#else
ccdbbb52 73 hThread = (HANDLE)_beginthreadex(NULL, stack_size, start_address, args, 0, &dwThreadId);
f2fdf1b5 74#endif
ccdbbb52
VK
75 if (hThread != NULL)
76 CloseHandle(hThread);
77 return (hThread != NULL);
78}
79
80inline THREAD ThreadCreateEx(THREAD_RESULT (THREAD_CALL *start_address )(void *), int stack_size, void *args)
81{
82 unsigned int dwThreadId;
83
631ec742 84#ifndef UNDER_CE
ccdbbb52 85 return (HANDLE)_beginthreadex(NULL, stack_size, start_address, args, 0, &dwThreadId);
631ec742
AK
86#else
87 return CreateThread(NULL, (DWORD)stack_size, (LPTHREAD_START_ROUTINE)start_address,
88 args, 0, (LPDWORD)&dwThreadId);
89#endif
54481027
VK
90}
91
92inline void ThreadExit(void)
93{
f2fdf1b5 94#ifdef UNDER_CE
018fda4d 95 ExitThread(0);
f2fdf1b5
VK
96#else
97 _endthreadex(0);
018fda4d 98#endif
54481027
VK
99}
100
ccdbbb52
VK
101inline void ThreadJoin(THREAD hThread)
102{
103 if (hThread != INVALID_THREAD_HANDLE)
104 {
105 WaitForSingleObject(hThread, INFINITE);
106 CloseHandle(hThread);
107 }
108}
109
54481027
VK
110inline MUTEX MutexCreate(void)
111{
112 return CreateMutex(NULL, FALSE, NULL);
113}
114
115inline void MutexDestroy(MUTEX mutex)
116{
117 CloseHandle(mutex);
118}
119
120inline BOOL MutexLock(MUTEX mutex, DWORD dwTimeOut)
121{
122 return WaitForSingleObject(mutex, dwTimeOut) == WAIT_OBJECT_0;
123}
124
125inline void MutexUnlock(MUTEX mutex)
126{
127 ReleaseMutex(mutex);
128}
129
d16cf8a5 130inline CONDITION ConditionCreate(BOOL bBroadcast)
54481027 131{
646d58de 132 return CreateEvent(NULL, bBroadcast, FALSE, NULL);
54481027
VK
133}
134
135inline void ConditionDestroy(CONDITION hCond)
136{
137 CloseHandle(hCond);
138}
139
140inline void ConditionSet(CONDITION hCond)
141{
39d7a7ed 142 PulseEvent(hCond);
54481027
VK
143}
144
c7f4f5a9 145inline BOOL ConditionWait(CONDITION hCond, DWORD dwTimeOut)
54481027 146{
c7f4f5a9 147 return WaitForSingleObject(hCond, dwTimeOut) == WAIT_OBJECT_0;
54481027
VK
148}
149
150#else /* _WIN32 */
151
d16cf8a5
AK
152/****************************************************************************/
153/* unix part */
154/****************************************************************************/
155
54481027 156#include <pthread.h>
d16cf8a5
AK
157#include <errno.h>
158#include <sys/time.h>
54481027
VK
159
160//
161// Related datatypes and constants
162//
163
7e679c4b
AK
164typedef pthread_t THREAD;
165typedef pthread_mutex_t * MUTEX;
d16cf8a5
AK
166struct condition_t
167{
168 pthread_cond_t cond;
169 pthread_mutex_t mutex;
170 BOOL broadcast;
171};
172typedef struct condition_t * CONDITION;
54481027 173
449e3da9
VK
174#define INVALID_MUTEX_HANDLE (NULL)
175#define INVALID_CONDITION_HANDLE (NULL)
ccdbbb52 176#define INVALID_THREAD_HANDLE 0
54481027 177
7e679c4b
AK
178#ifndef INFINITE
179# define INFINITE 0
180#endif
54481027 181
ccdbbb52
VK
182typedef void *THREAD_RESULT;
183
184#define THREAD_OK ((void *)0)
185#define THREAD_CALL
186
187
54481027
VK
188//
189// Inline functions
190//
191
d16cf8a5 192inline void ThreadSleep(int nSeconds)
54481027 193{
22412a01
VK
194#ifdef _NETWARE
195 sleep(nSeconds);
196#else
d16cf8a5
AK
197 struct timeval tv;
198
199 tv.tv_sec = nSeconds;
200 tv.tv_usec = 0;
201
202 select(1, NULL, NULL, NULL, &tv);
22412a01 203#endif
54481027
VK
204}
205
206inline void ThreadSleepMs(DWORD dwMilliseconds)
207{
d16cf8a5 208 // select is a sort of overkill
54481027
VK
209 usleep(dwMilliseconds * 1000); // Convert to microseconds
210}
211
ccdbbb52 212inline BOOL ThreadCreate(THREAD_RESULT (THREAD_CALL *start_address )(void *), int stack_size, void *args)
7e679c4b
AK
213{
214 THREAD id;
215
ccdbbb52 216 if (pthread_create(&id, NULL, start_address, args) == 0)
d1fbf6ba
VK
217 {
218 pthread_detach(id);
ccdbbb52
VK
219 return TRUE;
220 }
221 else
222 {
223 return FALSE;
224 }
225}
226
227inline THREAD ThreadCreateEx(THREAD_RESULT (THREAD_CALL *start_address )(void *), int stack_size, void *args)
228{
35a3a09e 229 THREAD id;
ccdbbb52 230
35a3a09e 231 if (pthread_create(&id, NULL, start_address, args) == 0)
ccdbbb52 232 {
35a3a09e
VK
233 return id;
234 }
d1fbf6ba
VK
235 else
236 {
35a3a09e
VK
237 return INVALID_THREAD_HANDLE;
238 }
7e679c4b
AK
239}
240
241inline void ThreadExit(void)
242{
521d90e7 243 pthread_exit(NULL);
7e679c4b
AK
244}
245
ccdbbb52
VK
246inline void ThreadJoin(THREAD hThread)
247{
248 if (hThread != INVALID_THREAD_HANDLE)
35a3a09e 249 pthread_join(hThread, NULL);
ccdbbb52
VK
250}
251
54481027
VK
252inline MUTEX MutexCreate(void)
253{
254 MUTEX mutex;
255
256 mutex = (MUTEX)malloc(sizeof(pthread_mutex_t));
257 if (mutex != NULL)
258 pthread_mutex_init(mutex, NULL);
259 return mutex;
260}
261
262inline void MutexDestroy(MUTEX mutex)
263{
7e679c4b 264 if (mutex != NULL) {
54481027
VK
265 pthread_mutex_destroy(mutex);
266 free(mutex);
267 }
268}
269
53c17a96 270inline BOOL MutexLock(MUTEX mutex, DWORD dwTimeOut)
54481027 271{
d16cf8a5
AK
272 int i;
273 int ret = FALSE;
274
7e679c4b 275 if (mutex != NULL) {
951e884e
AK
276 if (dwTimeOut == INFINITE)
277 {
278 if (pthread_mutex_lock(mutex) == 0) {
d16cf8a5 279 ret = TRUE;
d16cf8a5 280 }
951e884e
AK
281 }
282 else
283 {
284 for (i = (dwTimeOut / 50) + 1; i > 0; i--) {
8a435919
VK
285 if (pthread_mutex_trylock(mutex) == 0)
286 {
951e884e
AK
287 ret = TRUE;
288 break;
289 }
02ed4cf1 290 ThreadSleepMs(50);
951e884e 291 }
d16cf8a5 292 }
7e679c4b 293 }
d16cf8a5 294 return ret;
54481027
VK
295}
296
297inline void MutexUnlock(MUTEX mutex)
298{
8a435919
VK
299 if (mutex != NULL)
300 {
54481027 301 pthread_mutex_unlock(mutex);
7e679c4b
AK
302 }
303}
304
d16cf8a5 305inline CONDITION ConditionCreate(BOOL bBroadcast)
7e679c4b
AK
306{
307 CONDITION cond;
308
d16cf8a5 309 cond = (CONDITION)malloc(sizeof(struct condition_t));
8a435919
VK
310 if (cond != NULL)
311 {
d16cf8a5
AK
312 pthread_cond_init(&cond->cond, NULL);
313 pthread_mutex_init(&cond->mutex, NULL);
314 cond->broadcast = bBroadcast;
7e679c4b 315 }
d16cf8a5 316
7e679c4b
AK
317 return cond;
318}
319
d16cf8a5 320inline void ConditionDestroy(CONDITION cond)
7e679c4b 321{
d16cf8a5
AK
322 if (cond != NULL)
323 {
324 pthread_cond_destroy(&cond->cond);
325 pthread_mutex_destroy(&cond->mutex);
326 free(cond);
7e679c4b
AK
327 }
328}
329
d16cf8a5 330inline void ConditionSet(CONDITION cond)
7e679c4b 331{
d16cf8a5
AK
332 if (cond != NULL)
333 {
334 pthread_mutex_lock(&cond->mutex);
02ed4cf1 335 if (cond->broadcast)
d16cf8a5
AK
336 {
337 pthread_cond_broadcast(&cond->cond);
338 }
339 else
340 {
341 pthread_cond_signal(&cond->cond);
342 }
343 pthread_mutex_unlock(&cond->mutex);
344 }
7e679c4b
AK
345}
346
d16cf8a5 347inline BOOL ConditionWait(CONDITION cond, DWORD dwTimeOut)
7e679c4b 348{
d16cf8a5
AK
349 BOOL ret = FALSE;
350
351 if (cond != NULL)
352 {
353 int retcode;
354
355 pthread_mutex_lock(&cond->mutex);
356
357 if (dwTimeOut != INFINITE)
358 {
696fc54f
VK
359#if HAVE_PTHREAD_COND_RELTIMEDWAIT_NP
360 struct timespec timeout;
361
362 timeout.tv_sec = dwTimeOut / 1000;
363 timeout.tv_nsec = (dwTimeOut % 1000) * 1000000;
364 retcode = pthread_cond_reltimedwait_np(&cond->cond, &cond->mutex, &timeout);
365#else
d16cf8a5
AK
366 struct timeval now;
367 struct timespec timeout;
368
369 gettimeofday(&now, NULL);
370 timeout.tv_sec = now.tv_sec + (dwTimeOut / 1000);
63d09869 371 timeout.tv_nsec = ( now.tv_usec + ( dwTimeOut % 1000 ) * 1000) * 1000;
bba4da8a 372 retcode = pthread_cond_timedwait(&cond->cond, &cond->mutex, &timeout);
696fc54f 373#endif
d16cf8a5
AK
374 }
375 else
376 {
377 retcode = pthread_cond_wait(&cond->cond, &cond->mutex);
7e679c4b 378 }
7e679c4b 379
d16cf8a5
AK
380 pthread_mutex_unlock(&cond->mutex);
381
382 if (retcode == 0)
383 {
384 ret = TRUE;
385 }
7e679c4b 386 }
d16cf8a5
AK
387
388 return ret;
54481027
VK
389}
390
391#endif /* _WIN32 */
392
393#endif /* _nms_threads_h_ */