- Added agent's configuration parameter EnabledCiphers
[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)
150{
39d7a7ed 151 PulseEvent(hCond);
54481027
VK
152}
153
c7f4f5a9 154inline BOOL ConditionWait(CONDITION hCond, DWORD dwTimeOut)
54481027 155{
c7f4f5a9 156 return WaitForSingleObject(hCond, dwTimeOut) == WAIT_OBJECT_0;
54481027
VK
157}
158
159#else /* _WIN32 */
160
d16cf8a5
AK
161/****************************************************************************/
162/* unix part */
163/****************************************************************************/
164
ae82f88f
VK
165#if HAVE__USR_INCLUDE_PTHREAD_H
166#include </usr/include/pthread.h>
167#else
54481027 168#include <pthread.h>
ae82f88f
VK
169#endif
170
d16cf8a5
AK
171#include <errno.h>
172#include <sys/time.h>
54481027
VK
173
174//
175// Related datatypes and constants
176//
177
7e679c4b
AK
178typedef pthread_t THREAD;
179typedef pthread_mutex_t * MUTEX;
d16cf8a5
AK
180struct condition_t
181{
182 pthread_cond_t cond;
183 pthread_mutex_t mutex;
184 BOOL broadcast;
185};
186typedef struct condition_t * CONDITION;
54481027 187
449e3da9
VK
188#define INVALID_MUTEX_HANDLE (NULL)
189#define INVALID_CONDITION_HANDLE (NULL)
ccdbbb52 190#define INVALID_THREAD_HANDLE 0
54481027 191
7e679c4b
AK
192#ifndef INFINITE
193# define INFINITE 0
194#endif
54481027 195
ccdbbb52
VK
196typedef void *THREAD_RESULT;
197
198#define THREAD_OK ((void *)0)
199#define THREAD_CALL
200
201
54481027
VK
202//
203// Inline functions
204//
205
d16cf8a5 206inline void ThreadSleep(int nSeconds)
54481027 207{
22412a01
VK
208#ifdef _NETWARE
209 sleep(nSeconds);
210#else
d16cf8a5
AK
211 struct timeval tv;
212
213 tv.tv_sec = nSeconds;
214 tv.tv_usec = 0;
215
216 select(1, NULL, NULL, NULL, &tv);
22412a01 217#endif
54481027
VK
218}
219
220inline void ThreadSleepMs(DWORD dwMilliseconds)
221{
d16cf8a5 222 // select is a sort of overkill
54481027
VK
223 usleep(dwMilliseconds * 1000); // Convert to microseconds
224}
225
ccdbbb52 226inline BOOL ThreadCreate(THREAD_RESULT (THREAD_CALL *start_address )(void *), int stack_size, void *args)
7e679c4b
AK
227{
228 THREAD id;
229
ccdbbb52 230 if (pthread_create(&id, NULL, start_address, args) == 0)
d1fbf6ba
VK
231 {
232 pthread_detach(id);
ccdbbb52
VK
233 return TRUE;
234 }
235 else
236 {
237 return FALSE;
238 }
239}
240
241inline THREAD ThreadCreateEx(THREAD_RESULT (THREAD_CALL *start_address )(void *), int stack_size, void *args)
242{
35a3a09e 243 THREAD id;
ccdbbb52 244
35a3a09e 245 if (pthread_create(&id, NULL, start_address, args) == 0)
ccdbbb52 246 {
35a3a09e
VK
247 return id;
248 }
d1fbf6ba
VK
249 else
250 {
35a3a09e
VK
251 return INVALID_THREAD_HANDLE;
252 }
7e679c4b
AK
253}
254
255inline void ThreadExit(void)
256{
521d90e7 257 pthread_exit(NULL);
7e679c4b
AK
258}
259
ccdbbb52
VK
260inline void ThreadJoin(THREAD hThread)
261{
262 if (hThread != INVALID_THREAD_HANDLE)
35a3a09e 263 pthread_join(hThread, NULL);
ccdbbb52
VK
264}
265
54481027
VK
266inline MUTEX MutexCreate(void)
267{
268 MUTEX mutex;
269
270 mutex = (MUTEX)malloc(sizeof(pthread_mutex_t));
271 if (mutex != NULL)
272 pthread_mutex_init(mutex, NULL);
273 return mutex;
274}
275
276inline void MutexDestroy(MUTEX mutex)
277{
7e679c4b 278 if (mutex != NULL) {
54481027
VK
279 pthread_mutex_destroy(mutex);
280 free(mutex);
281 }
282}
283
53c17a96 284inline BOOL MutexLock(MUTEX mutex, DWORD dwTimeOut)
54481027 285{
d16cf8a5
AK
286 int i;
287 int ret = FALSE;
288
7e679c4b 289 if (mutex != NULL) {
951e884e
AK
290 if (dwTimeOut == INFINITE)
291 {
292 if (pthread_mutex_lock(mutex) == 0) {
d16cf8a5 293 ret = TRUE;
d16cf8a5 294 }
951e884e
AK
295 }
296 else
297 {
298 for (i = (dwTimeOut / 50) + 1; i > 0; i--) {
8a435919
VK
299 if (pthread_mutex_trylock(mutex) == 0)
300 {
951e884e
AK
301 ret = TRUE;
302 break;
303 }
02ed4cf1 304 ThreadSleepMs(50);
951e884e 305 }
d16cf8a5 306 }
7e679c4b 307 }
d16cf8a5 308 return ret;
54481027
VK
309}
310
311inline void MutexUnlock(MUTEX mutex)
312{
8a435919
VK
313 if (mutex != NULL)
314 {
54481027 315 pthread_mutex_unlock(mutex);
7e679c4b
AK
316 }
317}
318
d16cf8a5 319inline CONDITION ConditionCreate(BOOL bBroadcast)
7e679c4b
AK
320{
321 CONDITION cond;
322
d16cf8a5 323 cond = (CONDITION)malloc(sizeof(struct condition_t));
8a435919
VK
324 if (cond != NULL)
325 {
d16cf8a5
AK
326 pthread_cond_init(&cond->cond, NULL);
327 pthread_mutex_init(&cond->mutex, NULL);
328 cond->broadcast = bBroadcast;
7e679c4b 329 }
d16cf8a5 330
7e679c4b
AK
331 return cond;
332}
333
d16cf8a5 334inline void ConditionDestroy(CONDITION cond)
7e679c4b 335{
d16cf8a5
AK
336 if (cond != NULL)
337 {
338 pthread_cond_destroy(&cond->cond);
339 pthread_mutex_destroy(&cond->mutex);
340 free(cond);
7e679c4b
AK
341 }
342}
343
d16cf8a5 344inline void ConditionSet(CONDITION cond)
7e679c4b 345{
d16cf8a5
AK
346 if (cond != NULL)
347 {
348 pthread_mutex_lock(&cond->mutex);
02ed4cf1 349 if (cond->broadcast)
d16cf8a5
AK
350 {
351 pthread_cond_broadcast(&cond->cond);
352 }
353 else
354 {
355 pthread_cond_signal(&cond->cond);
356 }
357 pthread_mutex_unlock(&cond->mutex);
358 }
7e679c4b
AK
359}
360
d16cf8a5 361inline BOOL ConditionWait(CONDITION cond, DWORD dwTimeOut)
7e679c4b 362{
d16cf8a5
AK
363 BOOL ret = FALSE;
364
365 if (cond != NULL)
366 {
367 int retcode;
368
369 pthread_mutex_lock(&cond->mutex);
370
371 if (dwTimeOut != INFINITE)
372 {
696fc54f
VK
373#if HAVE_PTHREAD_COND_RELTIMEDWAIT_NP
374 struct timespec timeout;
375
376 timeout.tv_sec = dwTimeOut / 1000;
377 timeout.tv_nsec = (dwTimeOut % 1000) * 1000000;
378 retcode = pthread_cond_reltimedwait_np(&cond->cond, &cond->mutex, &timeout);
379#else
d16cf8a5
AK
380 struct timeval now;
381 struct timespec timeout;
382
ed452de5
AK
383 // note.
384 // mili - 10^-3
385 // micro - 10^-6
386 // nano - 10^-9
387
1216cc73 388 // FIXME there should be more accurate way
d16cf8a5
AK
389 gettimeofday(&now, NULL);
390 timeout.tv_sec = now.tv_sec + (dwTimeOut / 1000);
1216cc73 391
ed452de5
AK
392 now.tv_usec += (dwTimeOut % 1000) * 1000;
393 timeout.tv_sec += now.tv_usec / 1000000;
394 timeout.tv_nsec = (now.tv_usec % 1000000) * 1000;
395
bba4da8a 396 retcode = pthread_cond_timedwait(&cond->cond, &cond->mutex, &timeout);
696fc54f 397#endif
d16cf8a5
AK
398 }
399 else
400 {
401 retcode = pthread_cond_wait(&cond->cond, &cond->mutex);
7e679c4b 402 }
7e679c4b 403
d16cf8a5
AK
404 pthread_mutex_unlock(&cond->mutex);
405
406 if (retcode == 0)
407 {
408 ret = TRUE;
409 }
7e679c4b 410 }
d16cf8a5
AK
411
412 return ret;
54481027
VK
413}
414
415#endif /* _WIN32 */
416
417#endif /* _nms_threads_h_ */