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