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