eVC++ workspace files
[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
VK
69#ifdef UNDER_CE
70 hThread = CreateThread(NULL, (DWORD)stack_size, start_address,
71 arglist, 0, &dwThreadId);
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
84 return (HANDLE)_beginthreadex(NULL, stack_size, start_address, args, 0, &dwThreadId);
54481027
VK
85}
86
87inline void ThreadExit(void)
88{
f2fdf1b5 89#ifdef UNDER_CE
018fda4d 90 ExitThread(0);
f2fdf1b5
VK
91#else
92 _endthreadex(0);
018fda4d 93#endif
54481027
VK
94}
95
ccdbbb52
VK
96inline void ThreadJoin(THREAD hThread)
97{
98 if (hThread != INVALID_THREAD_HANDLE)
99 {
100 WaitForSingleObject(hThread, INFINITE);
101 CloseHandle(hThread);
102 }
103}
104
54481027
VK
105inline MUTEX MutexCreate(void)
106{
107 return CreateMutex(NULL, FALSE, NULL);
108}
109
110inline void MutexDestroy(MUTEX mutex)
111{
112 CloseHandle(mutex);
113}
114
115inline BOOL MutexLock(MUTEX mutex, DWORD dwTimeOut)
116{
117 return WaitForSingleObject(mutex, dwTimeOut) == WAIT_OBJECT_0;
118}
119
120inline void MutexUnlock(MUTEX mutex)
121{
122 ReleaseMutex(mutex);
123}
124
d16cf8a5 125inline CONDITION ConditionCreate(BOOL bBroadcast)
54481027 126{
646d58de 127 return CreateEvent(NULL, bBroadcast, FALSE, NULL);
54481027
VK
128}
129
130inline void ConditionDestroy(CONDITION hCond)
131{
132 CloseHandle(hCond);
133}
134
135inline void ConditionSet(CONDITION hCond)
136{
39d7a7ed 137 PulseEvent(hCond);
54481027
VK
138}
139
c7f4f5a9 140inline BOOL ConditionWait(CONDITION hCond, DWORD dwTimeOut)
54481027 141{
c7f4f5a9 142 return WaitForSingleObject(hCond, dwTimeOut) == WAIT_OBJECT_0;
54481027
VK
143}
144
145#else /* _WIN32 */
146
d16cf8a5
AK
147/****************************************************************************/
148/* unix part */
149/****************************************************************************/
150
54481027 151#include <pthread.h>
d16cf8a5
AK
152#include <errno.h>
153#include <sys/time.h>
54481027
VK
154
155//
156// Related datatypes and constants
157//
158
7e679c4b
AK
159typedef pthread_t THREAD;
160typedef pthread_mutex_t * MUTEX;
d16cf8a5
AK
161struct condition_t
162{
163 pthread_cond_t cond;
164 pthread_mutex_t mutex;
165 BOOL broadcast;
166};
167typedef struct condition_t * CONDITION;
54481027 168
449e3da9
VK
169#define INVALID_MUTEX_HANDLE (NULL)
170#define INVALID_CONDITION_HANDLE (NULL)
ccdbbb52 171#define INVALID_THREAD_HANDLE 0
54481027 172
7e679c4b
AK
173#ifndef INFINITE
174# define INFINITE 0
175#endif
54481027 176
ccdbbb52
VK
177typedef void *THREAD_RESULT;
178
179#define THREAD_OK ((void *)0)
180#define THREAD_CALL
181
182
54481027
VK
183//
184// Inline functions
185//
186
d16cf8a5 187inline void ThreadSleep(int nSeconds)
54481027 188{
22412a01
VK
189#ifdef _NETWARE
190 sleep(nSeconds);
191#else
d16cf8a5
AK
192 struct timeval tv;
193
194 tv.tv_sec = nSeconds;
195 tv.tv_usec = 0;
196
197 select(1, NULL, NULL, NULL, &tv);
22412a01 198#endif
54481027
VK
199}
200
201inline void ThreadSleepMs(DWORD dwMilliseconds)
202{
d16cf8a5 203 // select is a sort of overkill
54481027
VK
204 usleep(dwMilliseconds * 1000); // Convert to microseconds
205}
206
ccdbbb52 207inline BOOL ThreadCreate(THREAD_RESULT (THREAD_CALL *start_address )(void *), int stack_size, void *args)
7e679c4b
AK
208{
209 THREAD id;
210
ccdbbb52 211 if (pthread_create(&id, NULL, start_address, args) == 0)
d1fbf6ba
VK
212 {
213 pthread_detach(id);
ccdbbb52
VK
214 return TRUE;
215 }
216 else
217 {
218 return FALSE;
219 }
220}
221
222inline THREAD ThreadCreateEx(THREAD_RESULT (THREAD_CALL *start_address )(void *), int stack_size, void *args)
223{
35a3a09e 224 THREAD id;
ccdbbb52 225
35a3a09e 226 if (pthread_create(&id, NULL, start_address, args) == 0)
ccdbbb52 227 {
35a3a09e
VK
228 return id;
229 }
d1fbf6ba
VK
230 else
231 {
35a3a09e
VK
232 return INVALID_THREAD_HANDLE;
233 }
7e679c4b
AK
234}
235
236inline void ThreadExit(void)
237{
521d90e7 238 pthread_exit(NULL);
7e679c4b
AK
239}
240
ccdbbb52
VK
241inline void ThreadJoin(THREAD hThread)
242{
243 if (hThread != INVALID_THREAD_HANDLE)
35a3a09e 244 pthread_join(hThread, NULL);
ccdbbb52
VK
245}
246
54481027
VK
247inline MUTEX MutexCreate(void)
248{
249 MUTEX mutex;
250
251 mutex = (MUTEX)malloc(sizeof(pthread_mutex_t));
252 if (mutex != NULL)
253 pthread_mutex_init(mutex, NULL);
254 return mutex;
255}
256
257inline void MutexDestroy(MUTEX mutex)
258{
7e679c4b 259 if (mutex != NULL) {
54481027
VK
260 pthread_mutex_destroy(mutex);
261 free(mutex);
262 }
263}
264
53c17a96 265inline BOOL MutexLock(MUTEX mutex, DWORD dwTimeOut)
54481027 266{
d16cf8a5
AK
267 int i;
268 int ret = FALSE;
269
7e679c4b 270 if (mutex != NULL) {
951e884e
AK
271 if (dwTimeOut == INFINITE)
272 {
273 if (pthread_mutex_lock(mutex) == 0) {
d16cf8a5 274 ret = TRUE;
d16cf8a5 275 }
951e884e
AK
276 }
277 else
278 {
279 for (i = (dwTimeOut / 50) + 1; i > 0; i--) {
8a435919
VK
280 if (pthread_mutex_trylock(mutex) == 0)
281 {
951e884e
AK
282 ret = TRUE;
283 break;
284 }
02ed4cf1 285 ThreadSleepMs(50);
951e884e 286 }
d16cf8a5 287 }
7e679c4b 288 }
d16cf8a5 289 return ret;
54481027
VK
290}
291
292inline void MutexUnlock(MUTEX mutex)
293{
8a435919
VK
294 if (mutex != NULL)
295 {
54481027 296 pthread_mutex_unlock(mutex);
7e679c4b
AK
297 }
298}
299
d16cf8a5 300inline CONDITION ConditionCreate(BOOL bBroadcast)
7e679c4b
AK
301{
302 CONDITION cond;
303
d16cf8a5 304 cond = (CONDITION)malloc(sizeof(struct condition_t));
8a435919
VK
305 if (cond != NULL)
306 {
d16cf8a5
AK
307 pthread_cond_init(&cond->cond, NULL);
308 pthread_mutex_init(&cond->mutex, NULL);
309 cond->broadcast = bBroadcast;
7e679c4b 310 }
d16cf8a5 311
7e679c4b
AK
312 return cond;
313}
314
d16cf8a5 315inline void ConditionDestroy(CONDITION cond)
7e679c4b 316{
d16cf8a5
AK
317 if (cond != NULL)
318 {
319 pthread_cond_destroy(&cond->cond);
320 pthread_mutex_destroy(&cond->mutex);
321 free(cond);
7e679c4b
AK
322 }
323}
324
d16cf8a5 325inline void ConditionSet(CONDITION cond)
7e679c4b 326{
d16cf8a5
AK
327 if (cond != NULL)
328 {
329 pthread_mutex_lock(&cond->mutex);
02ed4cf1 330 if (cond->broadcast)
d16cf8a5
AK
331 {
332 pthread_cond_broadcast(&cond->cond);
333 }
334 else
335 {
336 pthread_cond_signal(&cond->cond);
337 }
338 pthread_mutex_unlock(&cond->mutex);
339 }
7e679c4b
AK
340}
341
d16cf8a5 342inline BOOL ConditionWait(CONDITION cond, DWORD dwTimeOut)
7e679c4b 343{
d16cf8a5
AK
344 BOOL ret = FALSE;
345
346 if (cond != NULL)
347 {
348 int retcode;
349
350 pthread_mutex_lock(&cond->mutex);
351
352 if (dwTimeOut != INFINITE)
353 {
696fc54f
VK
354#if HAVE_PTHREAD_COND_RELTIMEDWAIT_NP
355 struct timespec timeout;
356
357 timeout.tv_sec = dwTimeOut / 1000;
358 timeout.tv_nsec = (dwTimeOut % 1000) * 1000000;
359 retcode = pthread_cond_reltimedwait_np(&cond->cond, &cond->mutex, &timeout);
360#else
d16cf8a5
AK
361 struct timeval now;
362 struct timespec timeout;
363
364 gettimeofday(&now, NULL);
365 timeout.tv_sec = now.tv_sec + (dwTimeOut / 1000);
63d09869 366 timeout.tv_nsec = ( now.tv_usec + ( dwTimeOut % 1000 ) * 1000) * 1000;
bba4da8a 367 retcode = pthread_cond_timedwait(&cond->cond, &cond->mutex, &timeout);
696fc54f 368#endif
d16cf8a5
AK
369 }
370 else
371 {
372 retcode = pthread_cond_wait(&cond->cond, &cond->mutex);
7e679c4b 373 }
7e679c4b 374
d16cf8a5
AK
375 pthread_mutex_unlock(&cond->mutex);
376
377 if (retcode == 0)
378 {
379 ret = TRUE;
380 }
7e679c4b 381 }
d16cf8a5
AK
382
383 return ret;
54481027
VK
384}
385
386#endif /* _WIN32 */
387
388#endif /* _nms_threads_h_ */