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