rllib  1
rlwthread.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  wthread.c - description
3  -------------------
4  begin : Sun Jan 02 2000
5  copyright : (C) 2001 by R. Lehrig
6  email : lehrig@t-online.de
7  ***************************************************************************/
8 
9 /***************************************************************************
10  * *
11  * This library is free software; you can redistribute it and/or modify *
12  * it under the terms of the GNU LESSER GENERAL PUBLIC LICENSE as *
13  * published by the Free Software Foundation *
14  * *
15  ***************************************************************************/
16 /***********************************************************************************
17 
18 Wrapper for posix threads (UNIX,VMS,windows)
19 
20 (C) R. Lehrig 2000 lehrig@t-online.de
21 
22 ***********************************************************************************/
23 #include <errno.h>
24 #include "rlwthread.h"
25 #ifdef RLUNIX
26 #include <sys/time.h>
27 #include <sys/socket.h>
28 #include <netinet/in.h>
29 #include <netdb.h>
30 #include <pthread.h>
31 #endif
32 
33 /***************************************/
34 /* init attributes with default values */
35 /***************************************/
37 {
38 #ifdef RLWIN32THREAD
39  memset(attr,0,sizeof(pthread_attr_t));
40  return 0;
41 #else
42  return pthread_attr_init(attr);
43 #endif
44 }
45 
46 /* #pdoku headerlevel 2 ^^wthread_create */
47 /*******************************************/
48 /* create a thread */
49 /* tid: returned thread_id */
50 /* attr: thread creation attributes */
51 /* func: thread start routine */
52 /* arg: parameter to thread start routine */
53 /*******************************************/
55  void *(*func)(void*), void *arg)
56 {
57 #ifdef RLWIN32THREAD
58  HANDLE handle;
59  int ThreadId;
60  int dwStackSize = 0;
61  if(attr != NULL) dwStackSize = attr->__stacksize;
62  handle = CreateThread( NULL, /* pointer to thread security attributes */
63  dwStackSize, /* initial thread stack size, in bytes */
64  (LPTHREAD_START_ROUTINE)func, /* pointer to thread function */
65  arg, /* argument for new thread */
66  0, /* creation flags */
67  (unsigned long *) &ThreadId /* pointer to returned thread identifier */
68  );
69  *tid = (pthread_t) handle;
70  if(handle == NULL) return -1;
71  else return 0;
72 #else
73  int ret = pthread_create(tid,attr,func,arg);
74  pthread_detach(*tid);
75  return ret;
76 #endif
77 }
78 
80 {
81 #ifdef RLWIN32THREAD
82  CloseHandle((HANDLE) *tid);
83 #else
84  if(tid == NULL) return;
85 #endif
86 }
87 
88 /**************************************************************/
89 /* terminate a thread */
90 /* call this function within a thread to terminate the thead */
91 /* or return from the thread start routine */
92 /* status: return value from the thread (see wthread_join) */
93 /**************************************************************/
94 void rlwthread_exit(void *status)
95 {
96 #ifdef RLWIN32THREAD
97  DWORD *ptr;
98  ptr = (DWORD *) status;
99  if(status == NULL) ExitThread((DWORD) 0);
100  else ExitThread(*ptr);
101 #else
102  pthread_exit(status);
103 #endif
104 }
105 
106 /* #pdoku headerlevel 2 ^^wthread_join */
107 /************************************/
108 /* wait for termination of thread */
109 /* tid: thread id */
110 /* status: return value from thread */
111 /************************************/
112 #define USE_OLD_JOIN
113 int rlwthread_join(pthread_t tid, void **status)
114 {
115 #ifdef RLWIN32THREAD
116 
117 #ifdef USE_OLD_JOIN
118  DWORD exitcode;
119  while(1)
120  {
121  GetExitCodeThread((HANDLE) tid,&exitcode);
122  if(exitcode != STILL_ACTIVE) return exitcode;
123  Sleep(10); /* sleep 10 msec */
124  }
125  if(status == NULL) return 0;
126 #else
127  int result = 1;
128  DWORD exitcode;
129  DWORD dwWait = WaitForSingleObject((HANDLE) tid, INFINITE);
130  if(dwWait == WAIT_OBJECT_0)
131  {
132  if(GetExitCodeThread((HANDLE) tid, &exitcode) == TRUE)
133  {
134  result = 0;
135  *status = (int) exitcode; // ???
136  }
137  else
138  {
139  result = GetLastError();
140  }
141  }
142  else if(dwWait == WAIT_FAILED)
143  {
144  result = GetLastError();
145  }
146  if(status) return result;
147  return result;
148 #endif
149 
150 #else
151  return pthread_join(tid,status);
152 #endif
153 }
154 
155 /**************************/
156 /* init a mutex */
157 /* mptr: pointer to mutex */
158 /* atrr: mutex atrributes */
159 /**************************/
161  const pthread_mutexattr_t *attr)
162 {
163 #ifdef RLWIN32THREAD
164  HANDLE handle = CreateMutex(NULL, FALSE, NULL);
165  if(handle) *mptr = handle;
166  //old InitializeCriticalSection(mptr);
167  if(attr) return 0;
168  return 0;
169 #else
170  return pthread_mutex_init(mptr,attr);
171 #endif
172 }
173 
174 /**************************/
175 /* destroy a mutex */
176 /* mptr: pointer to mutex */
177 /**************************/
179 {
180 #ifdef RLWIN32THREAD
181  CloseHandle(*mptr);
182  //old DeleteCriticalSection(mptr);
183  return 0;
184 #else
185  return pthread_mutex_destroy(mptr);
186 #endif
187 }
188 
189 /**************************/
190 /* lock a mutex */
191 /* mptr: pointer to mutex */
192 /**************************/
194 {
195 #ifdef RLWIN32THREAD
196  if(WaitForSingleObject(*mptr, INFINITE) == WAIT_OBJECT_0) return 0;
197  //old EnterCriticalSection(mptr); // pointer to critical section object
198  return 0;
199 #else
200  return pthread_mutex_lock(mptr);
201 #endif
202 }
203 
204 /********************************/
205 /* try to lock a mutex */
206 /* mptr: pointer to mutex */
207 /* return 0 if already locked */
208 /* return !0 if lock sucessfull */
209 /********************************/
210 
211 #ifdef RLWIN32THREAD
212 WINBASEAPI BOOL WINAPI TryEnterCriticalSection( LPCRITICAL_SECTION lpCriticalSection);
213 #endif
214 
216 {
217 #ifdef RLWIN32THREAD
218  DWORD ret;
219 
220  ret = WaitForSingleObject(*mptr, 0);
221  if(ret == WAIT_OBJECT_0) return 1;
222  return 0;
223  //old ret = TryEnterCriticalSection(mptr); // pointer to critical section object
224  return ret;
225 #else
226  int ret;
227 
228  ret = pthread_mutex_trylock(mptr);
229  if(ret == EBUSY) return 0;
230  return 1;
231 #endif
232 }
233 
234 /**************************/
235 /* unlock a mutex */
236 /* mptr: pointer to mutex */
237 /**************************/
239 {
240 #ifdef RLWIN32THREAD
241  ReleaseMutex(*mptr);
242  //old LeaveCriticalSection(mptr);
243  return 0;
244 #else
245  return pthread_mutex_unlock(mptr);
246 #endif
247 }
248 
249 /**************************/
250 /* kill a thread */
251 /* tid handel of thread */
252 /**************************/
254 {
255 #ifdef RLWIN32THREAD
256  return (int) CloseHandle((HANDLE) tid);
257 #else
258  return pthread_cancel(tid);
259 #endif
260 }
261 
262 /***********************************************/
263 /* initialize a semaphore */
264 /* s is a pointer to a WSEMAPHORE struct */
265 /* cmax is the maximum number of the semaphore */
266 /* return 0 */
267 /***********************************************/
269 {
270 /* Create a semaphore with initial count=0 max. counts of cmax. */
271 #ifdef RLWIN32THREAD
272 
273  s->cmax = cmax;
274  s->hSemaphore = CreateSemaphore(
275  NULL, /* no security attributes */
276  0, /* initial count */
277  cmax, /* maximum count */
278  NULL); /* unnamed semaphore */
279 
280  if(s->hSemaphore == NULL) return -1; /* Check for error. */
281  return 0;
282 
283 #else
284 
285  s->cmax = cmax;
286  s->nready = 0;
287  rlwthread_mutex_init(&s->mutex, NULL);
288  pthread_cond_init(&s->cond, NULL);
289  return 0;
290 
291 #endif
292 }
293 
295 {
296 #ifdef RLWIN32THREAD
297  CloseHandle(s->hSemaphore);
298 #else
299  rlwthread_mutex_destroy(&s->mutex);
300 #endif
301  return 0;
302 }
303 
304 /***********************************************************************/
305 /* increment a semaphore */
306 /* s is a pointer to a WSEMAPHORE struct */
307 /* the producer will call this function whenever new data is available */
308 /* return 0=OK -1=error */
309 /***********************************************************************/
311 {
312 /* Increment the count of the semaphore. */
313 #ifdef RLWIN32THREAD
314 
315  if(!ReleaseSemaphore(
316  s->hSemaphore, /* handle of semaphore */
317  1, /* increase count by one */
318  NULL) ) /* not interested in previous count */
319  {
320  return -1; /* Deal with the error. */
321  }
322  return 0;
323 
324 #else
325 
326  pthread_mutex_lock(&s->mutex);
327  if(s->nready == 0) pthread_cond_signal(&s->cond);
328  s->nready++;
329  pthread_mutex_unlock(&s->mutex);
330  return 0;
331 
332 #endif
333 }
334 
335 /*********************************************************************************/
336 /* wait for a semaphore */
337 /* s is a pointer to a WSEMAPHORE struct */
338 /* the consumer will call this function to wait for new data to become available */
339 /* return 0 */
340 /*********************************************************************************/
342 {
343 #ifdef RLWIN32THREAD
344 
345  int ret;
346  ret = WaitForSingleObject(
347  s->hSemaphore, /* handle of semaphore */
348  INFINITE); /* infinite time-out interval */
349  if(ret) return 0;
350  return 0;
351 
352 #else
353 
354  pthread_mutex_lock(&s->mutex);
355  while(s->nready == 0)
356  {
357  pthread_cond_wait(&s->cond,&s->mutex);
358  }
359  s->nready--;
360  pthread_mutex_unlock(&s->mutex);
361  return 0;
362 
363 #endif
364 }
365 
366 int rlwthread_sleep(long msec)
367 {
368 #ifdef RLWIN32
369  Sleep(msec);
370  return 0;
371 #endif
372 
373 #ifdef RLUNIX
374  fd_set wset,rset,eset;
375  struct timeval timeout;
376 
377  FD_ZERO(&rset);
378  FD_ZERO(&wset);
379  FD_ZERO(&eset);
380  timeout.tv_sec = msec / 1000;
381  timeout.tv_usec = (msec % 1000) * 1000;
382  select(1,&rset,&wset,&eset,&timeout);
383  return 0;
384 #endif
385 
386 #ifdef __VMS
387  struct timespec interval;
388 
389  interval.tv_sec = msec / 1000;
390  interval.tv_nsec = (msec % 1000) * 1000 * 1000; /* wait msec msec */
391  pthread_delay_np(&interval);
392  return 0;
393 #endif
394 }
395 
396 void rlsleep(long msec)
397 {
398  rlwthread_sleep(msec);
399 }
400 /*** test routine ***/
401 /**************************************************************/
402 /* This is an example how to use the wthread_xxx functions */
403 /**************************************************************/
404 #define TESTINGx
405 #ifdef TESTING
406 #include "stdio.h"
407 #include "stdlib.h"
408 #ifndef RLWIN32
409 #include "unistd.h"
410 #endif
411 
412 /******************************************/
413 /* here we define 2 mutexes (semaphores) */
414 /* the mutexes are global two all threads */
415 /******************************************/
416 pthread_mutex_t mutex1, mutex2;
417 WSEMAPHORE semaphore;
418 
419 /************************************************************************/
420 /* this is the tread function */
421 /* it's name is given as parameter to wthread_create */
422 /* *arg is an argument given by the last parameter of wthread_create */
423 /* you can get the return value by pthread_join (status) */
424 /************************************************************************/
425 void *thread(void *arg)
426 {
427  int i=0;
428  printf("thread start : %s\n",(const char *) arg);
429  while(i++ < 50)
430  {
431  rlwrapwait_semaphore(&semaphore);
432  printf("thread %d\n",i);
433  /* sleep(1); */
434  }
435  return NULL;
436 }
437 
438 int main()
439 {
440  pthread_t tid; /* this is the thread_id */
441  void *status; /* this is the return value of the tread */
442  int i;
443 
444  /*****************************************************************************/
445  /* here we initialize 2 mutexes */
446  /* the mutexes are defined global to all threads */
447  /* for compatibility with MSWINDOWS the second parameter should be NULL */
448  /* */
449  /* in order to mark critical sections we can now use the following functions */
450  /* wthread_mutex_lock */
451  /* wthread_mutex_unlock */
452  /* if a mutex is locked by a thread and an other thread is calling */
453  /* wthread_mutex_lock it will be blocked until the first thread calls */
454  /* the wthread_mutex_unlock function */
455  /* */
456  /* this function is the reverse of wthread_mutex_init */
457  /* wthread_mutex_destroy */
458  /*****************************************************************************/
459  rlwthread_mutex_init(&mutex1, NULL);
460  rlwthread_mutex_init(&mutex2, NULL);
461 
462  rlwrapinit_semaphore(&semaphore, 1000);
463  printf("create a thread\n");
464  /****************************************************************/
465  /* this call will create a new thread */
466  /* tid is the returned thread_id */
467  /* you can use this id for example in wthread_join */
468  /* in this example the second parameter is NULL */
469  /* you can call wthread_attr_init(pthread_attr_t *attr) */
470  /* to initialize the start attributes */
471  /* pthread_attr_t attr; */
472  /* wthread_attr_init(&attr); */
473  /* wthread_create(&tid, &attr, thread, "hello thread"); */
474  /* thread is the name of the thread function (see above) */
475  /* the last parameter is given to the thread function */
476  /****************************************************************/
477  rlwthread_create(&tid, NULL, thread, "hello thread");
478 
479  i=0;
480  while(i++ < 50)
481  {
482  printf("main %d\n",i);
483  rlwrapincrement_semaphore(&semaphore);
484  if(i%4 == 0) Sleep(10);
485  }
486 
487  printf("waiting for thread\n");
488  /*****************************************************/
489  /* this call waits for the termination of thread tid */
490  /* the return value of the thread is given to status */
491  /*****************************************************/
492  rlwthread_join(tid, &status);
493  printf("finish\n");
494  return 0;
495 }
496 #endif
int rlwthread_mutex_destroy(pthread_mutex_t *mptr)
Definition: rlwthread.cpp:178
int rlwthread_attr_init(pthread_attr_t *attr)
Definition: rlwthread.cpp:36
void rlwthread_close_handle(pthread_t *tid)
Definition: rlwthread.cpp:79
HANDLE hSemaphore
Definition: rlwthread.h:88
int rlwthread_cancel(pthread_t tid)
Definition: rlwthread.cpp:253
int rlwthread_mutex_init(pthread_mutex_t *mptr, const pthread_mutexattr_t *attr)
Definition: rlwthread.cpp:160
void rlwthread_exit(void *status)
Definition: rlwthread.cpp:94
int rlwthread_mutex_lock(pthread_mutex_t *mptr)
Definition: rlwthread.cpp:193
size_t __stacksize
Definition: rlwthread.h:67
int rlwthread_mutex_trylock(pthread_mutex_t *mptr)
Definition: rlwthread.cpp:215
int cmax
Definition: rlwthread.h:87
WINBASEAPI BOOL WINAPI TryEnterCriticalSection(LPCRITICAL_SECTION lpCriticalSection)
int rlwthread_join(pthread_t tid, void **status)
Definition: rlwthread.cpp:113
HANDLE pthread_mutex_t
Definition: rlwthread.h:70
int main()
Definition: rlcorba.cpp:18
unsigned long int pthread_t
Definition: rlwthread.h:49
void rlsleep(long msec)
Definition: rlwthread.cpp:396
int rlwrapincrement_semaphore(WSEMAPHORE *s)
Definition: rlwthread.cpp:310
int rlwrapinit_semaphore(WSEMAPHORE *s, int cmax)
Definition: rlwthread.cpp:268
int rlwthread_mutex_unlock(pthread_mutex_t *mptr)
Definition: rlwthread.cpp:238
long pthread_mutexattr_t
Definition: rlwthread.h:72
int rlwthread_create(pthread_t *tid, const pthread_attr_t *attr, void *(*func)(void *), void *arg)
Definition: rlwthread.cpp:54
int rlwrapwait_semaphore(WSEMAPHORE *s)
Definition: rlwthread.cpp:341
int rlwrapdestroy_semaphore(WSEMAPHORE *s)
Definition: rlwthread.cpp:294
int rlwthread_sleep(long msec)
Definition: rlwthread.cpp:366