Portability fixes
[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
38#define INVALID_MUTEX_HANDLE INVALID_HANDLE_VALUE
39
40
41//
42// Inline functions
43//
44
45inline void ThreadSleep(int iSeconds)
46{
47 Sleep((DWORD)iSeconds * 1000); // Convert to milliseconds
48}
49
50inline void ThreadSleepMs(DWORD dwMilliseconds)
51{
52 Sleep(dwMilliseconds);
53}
54
55inline THREAD ThreadCreate(void (__cdecl *start_address )(void *), int stack_size, void *args)
56{
57 return (THREAD)_beginthread(start_address, stack_size, args);
58}
59
60inline void ThreadExit(void)
61{
62 _endthread();
63}
64
65inline MUTEX MutexCreate(void)
66{
67 return CreateMutex(NULL, FALSE, NULL);
68}
69
70inline void MutexDestroy(MUTEX mutex)
71{
72 CloseHandle(mutex);
73}
74
75inline BOOL MutexLock(MUTEX mutex, DWORD dwTimeOut)
76{
77 return WaitForSingleObject(mutex, dwTimeOut) == WAIT_OBJECT_0;
78}
79
80inline void MutexUnlock(MUTEX mutex)
81{
82 ReleaseMutex(mutex);
83}
84
d16cf8a5 85inline CONDITION ConditionCreate(BOOL bBroadcast)
54481027 86{
646d58de 87 return CreateEvent(NULL, bBroadcast, FALSE, NULL);
54481027
VK
88}
89
90inline void ConditionDestroy(CONDITION hCond)
91{
92 CloseHandle(hCond);
93}
94
95inline void ConditionSet(CONDITION hCond)
96{
97 SetEvent(hCond);
98}
99
c7f4f5a9 100inline BOOL ConditionWait(CONDITION hCond, DWORD dwTimeOut)
54481027 101{
c7f4f5a9 102 return WaitForSingleObject(hCond, dwTimeOut) == WAIT_OBJECT_0;
54481027
VK
103}
104
105#else /* _WIN32 */
106
d16cf8a5
AK
107/****************************************************************************/
108/* unix part */
109/****************************************************************************/
110
54481027 111#include <pthread.h>
d16cf8a5
AK
112#include <errno.h>
113#include <sys/time.h>
54481027
VK
114
115//
116// Related datatypes and constants
117//
118
7e679c4b
AK
119typedef pthread_t THREAD;
120typedef pthread_mutex_t * MUTEX;
d16cf8a5
AK
121struct condition_t
122{
123 pthread_cond_t cond;
124 pthread_mutex_t mutex;
125 BOOL broadcast;
126};
127typedef struct condition_t * CONDITION;
54481027
VK
128
129#define INVALID_MUTEX_HANDLE NULL
130
7e679c4b
AK
131#ifndef INFINITE
132# define INFINITE 0
133#endif
54481027
VK
134
135//
136// Inline functions
137//
138
d16cf8a5 139inline void ThreadSleep(int nSeconds)
54481027 140{
d16cf8a5
AK
141 struct timeval tv;
142
143 tv.tv_sec = nSeconds;
144 tv.tv_usec = 0;
145
146 select(1, NULL, NULL, NULL, &tv);
54481027
VK
147}
148
149inline void ThreadSleepMs(DWORD dwMilliseconds)
150{
d16cf8a5 151 // select is a sort of overkill
54481027
VK
152 usleep(dwMilliseconds * 1000); // Convert to microseconds
153}
154
93e601e5 155inline THREAD ThreadCreate(void (*start_address )(void *), int stack_size, void *args)
7e679c4b
AK
156{
157 THREAD id;
158
93e601e5 159 if (pthread_create(&id, NULL, (void *(*)(void *))start_address, args) == 0) {
7e679c4b
AK
160 return id;
161 } else {
162 return 0;
163 }
164}
165
166inline void ThreadExit(void)
167{
521d90e7 168 pthread_exit(NULL);
7e679c4b
AK
169}
170
54481027
VK
171inline MUTEX MutexCreate(void)
172{
173 MUTEX mutex;
174
175 mutex = (MUTEX)malloc(sizeof(pthread_mutex_t));
176 if (mutex != NULL)
177 pthread_mutex_init(mutex, NULL);
178 return mutex;
179}
180
181inline void MutexDestroy(MUTEX mutex)
182{
7e679c4b 183 if (mutex != NULL) {
54481027
VK
184 pthread_mutex_destroy(mutex);
185 free(mutex);
186 }
187}
188
53c17a96 189inline BOOL MutexLock(MUTEX mutex, DWORD dwTimeOut)
54481027 190{
d16cf8a5
AK
191 int i;
192 int ret = FALSE;
193
7e679c4b 194 if (mutex != NULL) {
951e884e
AK
195 if (dwTimeOut == INFINITE)
196 {
197 if (pthread_mutex_lock(mutex) == 0) {
d16cf8a5 198 ret = TRUE;
d16cf8a5 199 }
951e884e
AK
200 }
201 else
202 {
203 for (i = (dwTimeOut / 50) + 1; i > 0; i--) {
204 if (pthread_mutex_trylock(mutex) != EBUSY) {
205 ret = TRUE;
206 break;
207 }
02ed4cf1 208 ThreadSleepMs(50);
951e884e 209 }
d16cf8a5 210 }
7e679c4b 211 }
d16cf8a5 212 return ret;
54481027
VK
213}
214
215inline void MutexUnlock(MUTEX mutex)
216{
7e679c4b 217 if (mutex != NULL) {
54481027 218 pthread_mutex_unlock(mutex);
7e679c4b
AK
219 }
220}
221
d16cf8a5 222inline CONDITION ConditionCreate(BOOL bBroadcast)
7e679c4b
AK
223{
224 CONDITION cond;
225
d16cf8a5 226 cond = (CONDITION)malloc(sizeof(struct condition_t));
7e679c4b 227 if (cond != NULL) {
d16cf8a5
AK
228 pthread_cond_init(&cond->cond, NULL);
229 pthread_mutex_init(&cond->mutex, NULL);
230 cond->broadcast = bBroadcast;
7e679c4b 231 }
d16cf8a5 232
7e679c4b
AK
233 return cond;
234}
235
d16cf8a5 236inline void ConditionDestroy(CONDITION cond)
7e679c4b 237{
d16cf8a5
AK
238 if (cond != NULL)
239 {
240 pthread_cond_destroy(&cond->cond);
241 pthread_mutex_destroy(&cond->mutex);
242 free(cond);
7e679c4b
AK
243 }
244}
245
d16cf8a5 246inline void ConditionSet(CONDITION cond)
7e679c4b 247{
d16cf8a5
AK
248 if (cond != NULL)
249 {
250 pthread_mutex_lock(&cond->mutex);
02ed4cf1 251 if (cond->broadcast)
d16cf8a5
AK
252 {
253 pthread_cond_broadcast(&cond->cond);
254 }
255 else
256 {
257 pthread_cond_signal(&cond->cond);
258 }
259 pthread_mutex_unlock(&cond->mutex);
260 }
7e679c4b
AK
261}
262
d16cf8a5 263inline BOOL ConditionWait(CONDITION cond, DWORD dwTimeOut)
7e679c4b 264{
d16cf8a5
AK
265 BOOL ret = FALSE;
266
267 if (cond != NULL)
268 {
269 int retcode;
270
271 pthread_mutex_lock(&cond->mutex);
272
273 if (dwTimeOut != INFINITE)
274 {
275 struct timeval now;
276 struct timespec timeout;
277
278 gettimeofday(&now, NULL);
279 timeout.tv_sec = now.tv_sec + (dwTimeOut / 1000);
280 timeout.tv_nsec = ( now.tv_usec + ( dwTimeOut % 1000 ) ) * 1000;
281 while (retcode != ETIMEDOUT) {
282 retcode = pthread_cond_timedwait(&cond->cond, &cond->mutex, &timeout);
283 }
284 }
285 else
286 {
287 retcode = pthread_cond_wait(&cond->cond, &cond->mutex);
7e679c4b 288 }
7e679c4b 289
d16cf8a5
AK
290 pthread_mutex_unlock(&cond->mutex);
291
292 if (retcode == 0)
293 {
294 ret = TRUE;
295 }
7e679c4b 296 }
d16cf8a5
AK
297
298 return ret;
54481027
VK
299}
300
301#endif /* _WIN32 */
302
303#endif /* _nms_threads_h_ */