Subversion Repositories HomeAutomation

Rev

Rev 1398 | Details | Compare with Previous | Last modification | View Log | SVN | RSS feed

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