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