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