- Both 32 and 6 bit installers works correctly
[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
b71bff93
VK
26#ifdef __cplusplus
27
28#define NMS_THREADS_H_INCLUDED
29
54481027
VK
30#ifdef _WIN32
31
018fda4d
AK
32#ifndef UNDER_CE
33# include <process.h>
34#endif
54481027
VK
35
36//
37// Related datatypes and constants
38//
39
dbe67493
VK
40typedef HANDLE MUTEX;
41typedef HANDLE THREAD;
42typedef HANDLE CONDITION;
54481027 43
449e3da9
VK
44#define INVALID_MUTEX_HANDLE INVALID_HANDLE_VALUE
45#define INVALID_CONDITION_HANDLE INVALID_HANDLE_VALUE
ccdbbb52
VK
46#define INVALID_THREAD_HANDLE (NULL)
47
288ddda4
VK
48#ifdef UNDER_CE
49typedef DWORD THREAD_RESULT;
50typedef DWORD THREAD_ID;
51#else
ccdbbb52 52typedef unsigned int THREAD_RESULT;
288ddda4
VK
53typedef unsigned int THREAD_ID;
54#endif
ccdbbb52
VK
55
56#define THREAD_OK 0
288ddda4
VK
57
58#ifdef UNDER_CE
59#define THREAD_CALL
60#else
ccdbbb52 61#define THREAD_CALL __stdcall
288ddda4 62#endif
54481027
VK
63
64
65//
66// Inline functions
67//
68
69inline void ThreadSleep(int iSeconds)
70{
71 Sleep((DWORD)iSeconds * 1000); // Convert to milliseconds
72}
73
74inline void ThreadSleepMs(DWORD dwMilliseconds)
75{
76 Sleep(dwMilliseconds);
77}
78
ccdbbb52 79inline BOOL ThreadCreate(THREAD_RESULT (THREAD_CALL *start_address )(void *), int stack_size, void *args)
54481027 80{
ccdbbb52 81 HANDLE hThread;
288ddda4 82 THREAD_ID dwThreadId;
ccdbbb52 83
f2fdf1b5 84#ifdef UNDER_CE
288ddda4 85 hThread = CreateThread(NULL, (DWORD)stack_size, start_address, args, 0, &dwThreadId);
f2fdf1b5 86#else
ccdbbb52 87 hThread = (HANDLE)_beginthreadex(NULL, stack_size, start_address, args, 0, &dwThreadId);
f2fdf1b5 88#endif
ccdbbb52
VK
89 if (hThread != NULL)
90 CloseHandle(hThread);
91 return (hThread != NULL);
92}
93
94inline THREAD ThreadCreateEx(THREAD_RESULT (THREAD_CALL *start_address )(void *), int stack_size, void *args)
95{
288ddda4 96 THREAD_ID dwThreadId;
ccdbbb52 97
288ddda4
VK
98#ifdef UNDER_CE
99 return CreateThread(NULL, (DWORD)stack_size, start_address, args, 0, &dwThreadId);
631ec742 100#else
288ddda4 101 return (HANDLE)_beginthreadex(NULL, stack_size, start_address, args, 0, &dwThreadId);
631ec742 102#endif
54481027
VK
103}
104
105inline void ThreadExit(void)
106{
f2fdf1b5 107#ifdef UNDER_CE
018fda4d 108 ExitThread(0);
f2fdf1b5
VK
109#else
110 _endthreadex(0);
018fda4d 111#endif
54481027
VK
112}
113
ccdbbb52
VK
114inline void ThreadJoin(THREAD hThread)
115{
116 if (hThread != INVALID_THREAD_HANDLE)
117 {
118 WaitForSingleObject(hThread, INFINITE);
119 CloseHandle(hThread);
120 }
121}
122
54481027
VK
123inline MUTEX MutexCreate(void)
124{
125 return CreateMutex(NULL, FALSE, NULL);
126}
127
128inline void MutexDestroy(MUTEX mutex)
129{
130 CloseHandle(mutex);
131}
132
133inline BOOL MutexLock(MUTEX mutex, DWORD dwTimeOut)
134{
135 return WaitForSingleObject(mutex, dwTimeOut) == WAIT_OBJECT_0;
136}
137
138inline void MutexUnlock(MUTEX mutex)
139{
140 ReleaseMutex(mutex);
141}
142
d16cf8a5 143inline CONDITION ConditionCreate(BOOL bBroadcast)
54481027 144{
646d58de 145 return CreateEvent(NULL, bBroadcast, FALSE, NULL);
54481027
VK
146}
147
148inline void ConditionDestroy(CONDITION hCond)
149{
150 CloseHandle(hCond);
151}
152
153inline void ConditionSet(CONDITION hCond)
5f743326
VK
154{
155 SetEvent(hCond);
156}
157
158inline void ConditionReset(CONDITION hCond)
159{
160 ResetEvent(hCond);
161}
162
163inline void ConditionPulse(CONDITION hCond)
54481027 164{
39d7a7ed 165 PulseEvent(hCond);
54481027
VK
166}
167
c7f4f5a9 168inline BOOL ConditionWait(CONDITION hCond, DWORD dwTimeOut)
54481027 169{
c7f4f5a9 170 return WaitForSingleObject(hCond, dwTimeOut) == WAIT_OBJECT_0;
54481027
VK
171}
172
173#else /* _WIN32 */
174
d16cf8a5
AK
175/****************************************************************************/
176/* unix part */
177/****************************************************************************/
178
54481027 179#include <pthread.h>
d16cf8a5
AK
180#include <errno.h>
181#include <sys/time.h>
54481027
VK
182
183//
184// Related datatypes and constants
185//
186
7e679c4b
AK
187typedef pthread_t THREAD;
188typedef pthread_mutex_t * MUTEX;
d16cf8a5
AK
189struct condition_t
190{
191 pthread_cond_t cond;
192 pthread_mutex_t mutex;
193 BOOL broadcast;
5f743326 194 BOOL isSet;
d16cf8a5
AK
195};
196typedef struct condition_t * CONDITION;
54481027 197
449e3da9
VK
198#define INVALID_MUTEX_HANDLE (NULL)
199#define INVALID_CONDITION_HANDLE (NULL)
ccdbbb52 200#define INVALID_THREAD_HANDLE 0
54481027 201
7e679c4b
AK
202#ifndef INFINITE
203# define INFINITE 0
204#endif
54481027 205
ccdbbb52
VK
206typedef void *THREAD_RESULT;
207
208#define THREAD_OK ((void *)0)
209#define THREAD_CALL
210
211
54481027
VK
212//
213// Inline functions
214//
215
d16cf8a5 216inline void ThreadSleep(int nSeconds)
54481027 217{
22412a01
VK
218#ifdef _NETWARE
219 sleep(nSeconds);
220#else
d16cf8a5
AK
221 struct timeval tv;
222
223 tv.tv_sec = nSeconds;
224 tv.tv_usec = 0;
225
226 select(1, NULL, NULL, NULL, &tv);
22412a01 227#endif
54481027
VK
228}
229
230inline void ThreadSleepMs(DWORD dwMilliseconds)
231{
d16cf8a5 232 // select is a sort of overkill
54481027
VK
233 usleep(dwMilliseconds * 1000); // Convert to microseconds
234}
235
ccdbbb52 236inline BOOL ThreadCreate(THREAD_RESULT (THREAD_CALL *start_address )(void *), int stack_size, void *args)
7e679c4b
AK
237{
238 THREAD id;
239
ccdbbb52 240 if (pthread_create(&id, NULL, start_address, args) == 0)
d1fbf6ba
VK
241 {
242 pthread_detach(id);
ccdbbb52
VK
243 return TRUE;
244 }
245 else
246 {
247 return FALSE;
248 }
249}
250
251inline THREAD ThreadCreateEx(THREAD_RESULT (THREAD_CALL *start_address )(void *), int stack_size, void *args)
252{
35a3a09e 253 THREAD id;
ccdbbb52 254
35a3a09e 255 if (pthread_create(&id, NULL, start_address, args) == 0)
ccdbbb52 256 {
35a3a09e
VK
257 return id;
258 }
d1fbf6ba
VK
259 else
260 {
35a3a09e
VK
261 return INVALID_THREAD_HANDLE;
262 }
7e679c4b
AK
263}
264
265inline void ThreadExit(void)
266{
521d90e7 267 pthread_exit(NULL);
7e679c4b
AK
268}
269
ccdbbb52
VK
270inline void ThreadJoin(THREAD hThread)
271{
272 if (hThread != INVALID_THREAD_HANDLE)
35a3a09e 273 pthread_join(hThread, NULL);
ccdbbb52
VK
274}
275
54481027
VK
276inline MUTEX MutexCreate(void)
277{
278 MUTEX mutex;
279
280 mutex = (MUTEX)malloc(sizeof(pthread_mutex_t));
281 if (mutex != NULL)
282 pthread_mutex_init(mutex, NULL);
283 return mutex;
284}
285
286inline void MutexDestroy(MUTEX mutex)
287{
7e679c4b 288 if (mutex != NULL) {
54481027
VK
289 pthread_mutex_destroy(mutex);
290 free(mutex);
291 }
292}
293
53c17a96 294inline BOOL MutexLock(MUTEX mutex, DWORD dwTimeOut)
54481027 295{
d16cf8a5
AK
296 int i;
297 int ret = FALSE;
298
7e679c4b 299 if (mutex != NULL) {
951e884e
AK
300 if (dwTimeOut == INFINITE)
301 {
302 if (pthread_mutex_lock(mutex) == 0) {
d16cf8a5 303 ret = TRUE;
d16cf8a5 304 }
951e884e
AK
305 }
306 else
307 {
308 for (i = (dwTimeOut / 50) + 1; i > 0; i--) {
8a435919
VK
309 if (pthread_mutex_trylock(mutex) == 0)
310 {
951e884e
AK
311 ret = TRUE;
312 break;
313 }
02ed4cf1 314 ThreadSleepMs(50);
951e884e 315 }
d16cf8a5 316 }
7e679c4b 317 }
d16cf8a5 318 return ret;
54481027
VK
319}
320
321inline void MutexUnlock(MUTEX mutex)
322{
8a435919
VK
323 if (mutex != NULL)
324 {
54481027 325 pthread_mutex_unlock(mutex);
7e679c4b
AK
326 }
327}
328
d16cf8a5 329inline CONDITION ConditionCreate(BOOL bBroadcast)
7e679c4b
AK
330{
331 CONDITION cond;
332
d16cf8a5 333 cond = (CONDITION)malloc(sizeof(struct condition_t));
8a435919
VK
334 if (cond != NULL)
335 {
d16cf8a5
AK
336 pthread_cond_init(&cond->cond, NULL);
337 pthread_mutex_init(&cond->mutex, NULL);
338 cond->broadcast = bBroadcast;
5f743326 339 cond->isSet = FALSE;
7e679c4b 340 }
d16cf8a5 341
7e679c4b
AK
342 return cond;
343}
344
d16cf8a5 345inline void ConditionDestroy(CONDITION cond)
7e679c4b 346{
5f743326 347 if (cond != INVALID_CONDITION_HANDLE)
d16cf8a5
AK
348 {
349 pthread_cond_destroy(&cond->cond);
350 pthread_mutex_destroy(&cond->mutex);
351 free(cond);
7e679c4b
AK
352 }
353}
354
d16cf8a5 355inline void ConditionSet(CONDITION cond)
7e679c4b 356{
5f743326 357 if (cond != INVALID_CONDITION_HANDLE)
d16cf8a5
AK
358 {
359 pthread_mutex_lock(&cond->mutex);
5f743326 360 cond->isSet = TRUE;
02ed4cf1 361 if (cond->broadcast)
d16cf8a5
AK
362 {
363 pthread_cond_broadcast(&cond->cond);
364 }
365 else
366 {
367 pthread_cond_signal(&cond->cond);
368 }
369 pthread_mutex_unlock(&cond->mutex);
370 }
7e679c4b
AK
371}
372
5f743326
VK
373inline void ConditionReset(CONDITION cond)
374{
375 if (cond != INVALID_CONDITION_HANDLE)
376 {
377 pthread_mutex_lock(&cond->mutex);
378 cond->isSet = FALSE;
379 pthread_mutex_unlock(&cond->mutex);
380 }
381}
382
383inline void ConditionPulse(CONDITION cond)
384{
385 if (cond != INVALID_CONDITION_HANDLE)
386 {
387 pthread_mutex_lock(&cond->mutex);
388 if (cond->broadcast)
389 {
390 pthread_cond_broadcast(&cond->cond);
391 }
392 else
393 {
394 pthread_cond_signal(&cond->cond);
395 }
396 cond->isSet = FALSE;
397 pthread_mutex_unlock(&cond->mutex);
398 }
399}
400
d16cf8a5 401inline BOOL ConditionWait(CONDITION cond, DWORD dwTimeOut)
7e679c4b 402{
d16cf8a5
AK
403 BOOL ret = FALSE;
404
405 if (cond != NULL)
406 {
407 int retcode;
408
409 pthread_mutex_lock(&cond->mutex);
5f743326
VK
410 if (cond->isSet)
411 {
412 ret = TRUE;
413 if (!cond->broadcast)
414 cond->isSet = FALSE;
415 }
416 else
417 {
418 if (dwTimeOut != INFINITE)
419 {
58e7e86f 420#if HAVE_PTHREAD_COND_RELTIMEDWAIT_NP || defined(_NETWARE)
5f743326 421 struct timespec timeout;
696fc54f 422
5f743326
VK
423 timeout.tv_sec = dwTimeOut / 1000;
424 timeout.tv_nsec = (dwTimeOut % 1000) * 1000000;
58e7e86f
VK
425#ifdef _NETWARE
426 retcode = pthread_cond_timedwait(&cond->cond, &cond->mutex, &timeout);
427#else
5f743326 428 retcode = pthread_cond_reltimedwait_np(&cond->cond, &cond->mutex, &timeout);
58e7e86f 429#endif
696fc54f 430#else
5f743326
VK
431 struct timeval now;
432 struct timespec timeout;
d16cf8a5 433
5f743326
VK
434 // note.
435 // mili - 10^-3
436 // micro - 10^-6
437 // nano - 10^-9
ed452de5 438
5f743326
VK
439 // FIXME there should be more accurate way
440 gettimeofday(&now, NULL);
441 timeout.tv_sec = now.tv_sec + (dwTimeOut / 1000);
1216cc73 442
5f743326
VK
443 now.tv_usec += (dwTimeOut % 1000) * 1000;
444 timeout.tv_sec += now.tv_usec / 1000000;
445 timeout.tv_nsec = (now.tv_usec % 1000000) * 1000;
ed452de5 446
5f743326 447 retcode = pthread_cond_timedwait(&cond->cond, &cond->mutex, &timeout);
696fc54f 448#endif
5f743326
VK
449 }
450 else
451 {
452 retcode = pthread_cond_wait(&cond->cond, &cond->mutex);
453 }
454
455 if (retcode == 0)
456 {
633907a4
VK
457 if (!cond->broadcast)
458 cond->isSet = FALSE;
5f743326
VK
459 ret = TRUE;
460 }
461 }
7e679c4b 462
d16cf8a5 463 pthread_mutex_unlock(&cond->mutex);
7e679c4b 464 }
d16cf8a5
AK
465
466 return ret;
54481027
VK
467}
468
bff234b8
VK
469inline DWORD GetCurrentProcessId(void)
470{
471 return getpid();
472}
473
54481027
VK
474#endif /* _WIN32 */
475
b71bff93
VK
476#endif /* __cplusplus */
477
54481027 478#endif /* _nms_threads_h_ */