rllib  1
rlwthread.cpp
Go to the documentation of this file.
00001 /***************************************************************************
00002                           wthread.c  -  description
00003                              -------------------
00004     begin                : Sun Jan 02 2000
00005     copyright            : (C) 2001 by Rainer Lehrig
00006     email                : lehrig@t-online.de
00007  ***************************************************************************/
00008 
00009 /***************************************************************************
00010  *                                                                         *
00011  *   This library is free software; you can redistribute it and/or modify  *
00012  *   it under the terms of the GNU LESSER GENERAL PUBLIC LICENSE as        *
00013  *   published by the Free Software Foundation                             *
00014  *                                                                         *
00015  ***************************************************************************/
00016 /***********************************************************************************
00017 
00018 Wrapper for posix threads (UNIX,VMS,windows)
00019 
00020 (C) Rainer Lehrig 2000                                       lehrig@t-online.de
00021 
00022 ***********************************************************************************/
00023 #include <errno.h>
00024 #include "rlwthread.h"
00025 #ifdef RLUNIX
00026 #include <sys/time.h>
00027 #include <sys/socket.h>
00028 #include <netinet/in.h>
00029 #include <netdb.h>
00030 #include <pthread.h>
00031 #endif
00032 
00033 /***************************************/
00034 /* init attributes with default values */
00035 /***************************************/
00036 int rlwthread_attr_init(pthread_attr_t *attr)
00037 {
00038 #ifdef RLWIN32
00039   memset(attr,0,sizeof(pthread_attr_t));
00040   return 0;
00041 #else
00042   return pthread_attr_init(attr);
00043 #endif
00044 }
00045 
00046 /* #pdoku headerlevel 2 ^^wthread_create */
00047 /*******************************************/
00048 /* create a thread                         */
00049 /* tid:  returned thread_id                */
00050 /* attr: thread creation attributes        */
00051 /* func: thread start routine              */
00052 /* arg:  parameter to thread start routine */
00053 /*******************************************/
00054 int rlwthread_create(pthread_t *tid, const pthread_attr_t *attr,
00055                       void *(*func)(void*), void *arg)
00056 {
00057 #ifdef RLWIN32
00058   HANDLE handle;
00059   int ThreadId;
00060   int dwStackSize = 0;
00061   if(attr != NULL) dwStackSize = attr->__stacksize;
00062   handle = CreateThread( NULL,                    /* pointer to thread security attributes */
00063                          dwStackSize,             /* initial thread stack size, in bytes   */
00064  (LPTHREAD_START_ROUTINE)func,                    /* pointer to thread function            */
00065                          arg,                     /* argument for new thread               */
00066                          0,                       /* creation flags                        */
00067        (unsigned long *) &ThreadId                /* pointer to returned thread identifier */
00068                        );
00069   *tid = (pthread_t) handle;
00070   if(handle == NULL) return -1;
00071   else               return 0;
00072 #else
00073   int ret = pthread_create(tid,attr,func,arg);
00074   pthread_detach(*tid);
00075   return ret;
00076 #endif
00077 }
00078 
00079 void rlwthread_close_handle(pthread_t *tid)
00080 {
00081 #ifdef RLWIN32
00082   CloseHandle((HANDLE) *tid);
00083 #else
00084   if(tid == NULL) return;
00085 #endif
00086 }
00087 
00088 /**************************************************************/
00089 /* terminate a thread                                         */
00090 /* call this function within a thread to terminate the thead  */
00091 /* or return from the thread start routine                    */
00092 /* status: return value from the thread (see wthread_join)    */
00093 /**************************************************************/
00094 void rlwthread_exit(void *status)
00095 {
00096 #ifdef RLWIN32
00097   DWORD *ptr;
00098   ptr = (DWORD *) status;
00099   if(status == NULL) ExitThread((DWORD) 0);
00100   else               ExitThread(*ptr);
00101 #else
00102   pthread_exit(status);
00103 #endif
00104 }
00105 
00106 /* #pdoku headerlevel 2 ^^wthread_join */
00107 /************************************/
00108 /* wait for termination of thread   */
00109 /* tid:    thread id                */
00110 /* status: return value from thread */
00111 /************************************/
00112 #define USE_OLD_JOIN
00113 int rlwthread_join(pthread_t tid, void **status)
00114 {
00115 #ifdef RLWIN32
00116 
00117 #ifdef USE_OLD_JOIN
00118   DWORD exitcode;
00119   while(1)
00120   {
00121     GetExitCodeThread((HANDLE) tid,&exitcode);
00122     if(exitcode != STILL_ACTIVE) return exitcode;
00123     Sleep(10); /* sleep 10 msec */
00124   }
00125 #else
00126   int result = 1;
00127   DWORD exitcode;
00128   DWORD dwWait = WaitForSingleObject((HANDLE) tid, INFINITE);
00129   if(dwWait == WAIT_OBJECT_0)
00130   {
00131     if(GetExitCodeThread((HANDLE) tid, &exitcode) == TRUE)
00132     {
00133       result = 0;
00134       *status = (int) exitcode; // ???
00135     }
00136     else
00137     {
00138       result = GetLastError();
00139     }
00140   }
00141   else if(dwWait == WAIT_FAILED)
00142   {
00143     result = GetLastError();
00144   }
00145   return result;
00146 #endif
00147 
00148 #else
00149   return pthread_join(tid,status);
00150 #endif
00151 }
00152 
00153 /**************************/
00154 /* init a mutex           */
00155 /* mptr: pointer to mutex */
00156 /* atrr: mutex atrributes */
00157 /**************************/
00158 int rlwthread_mutex_init(pthread_mutex_t *mptr,
00159                           const pthread_mutexattr_t *attr)
00160 {
00161 #ifdef RLWIN32
00162   HANDLE handle = CreateMutex(NULL, FALSE, NULL);
00163   if(handle) *mptr = handle;
00164   //old InitializeCriticalSection(mptr);
00165   return 0;
00166 #else
00167   return pthread_mutex_init(mptr,attr);
00168 #endif
00169 }
00170 
00171 /**************************/
00172 /* destroy a mutex        */
00173 /* mptr: pointer to mutex */
00174 /**************************/
00175 int rlwthread_mutex_destroy(pthread_mutex_t *mptr)
00176 {
00177 #ifdef RLWIN32
00178   CloseHandle(*mptr);
00179   //old DeleteCriticalSection(mptr);
00180   return 0;
00181 #else
00182   return pthread_mutex_destroy(mptr);
00183 #endif
00184 }
00185 
00186 /**************************/
00187 /* lock a mutex           */
00188 /* mptr: pointer to mutex */
00189 /**************************/
00190 int rlwthread_mutex_lock(pthread_mutex_t *mptr)
00191 {
00192 #ifdef RLWIN32
00193   if(WaitForSingleObject(*mptr, INFINITE) == WAIT_OBJECT_0) return 0;
00194   //old EnterCriticalSection(mptr); // pointer to critical section object
00195   return 0;
00196 #else
00197   return pthread_mutex_lock(mptr);
00198 #endif
00199 }
00200 
00201 /********************************/
00202 /* try to lock a mutex          */
00203 /* mptr: pointer to mutex       */
00204 /* return 0 if already locked   */
00205 /* return !0 if lock sucessfull */
00206 /********************************/
00207 
00208 #ifdef RLWIN32
00209 WINBASEAPI BOOL WINAPI TryEnterCriticalSection( LPCRITICAL_SECTION lpCriticalSection);
00210 #endif
00211 
00212 int rlwthread_mutex_trylock(pthread_mutex_t *mptr)
00213 {
00214 #ifdef RLWIN32
00215   DWORD ret;
00216 
00217   ret = WaitForSingleObject(*mptr, 0);
00218   if(ret == WAIT_OBJECT_0) return 1;
00219   return 0;
00220   //old ret = TryEnterCriticalSection(mptr); // pointer to critical section object
00221   return ret;
00222 #else
00223   int ret;
00224 
00225   ret = pthread_mutex_trylock(mptr);
00226   if(ret == EBUSY) return 0;
00227   return 1;
00228 #endif
00229 }
00230 
00231 /**************************/
00232 /* unlock a mutex         */
00233 /* mptr: pointer to mutex */
00234 /**************************/
00235 int rlwthread_mutex_unlock(pthread_mutex_t *mptr)
00236 {
00237 #ifdef RLWIN32
00238   ReleaseMutex(*mptr);
00239   //old LeaveCriticalSection(mptr);
00240   return 0;
00241 #else
00242   return pthread_mutex_unlock(mptr);
00243 #endif
00244 }
00245 
00246 /**************************/
00247 /* kill a thread          */
00248 /* tid handel of thread   */
00249 /**************************/
00250 int rlwthread_cancel(pthread_t tid)
00251 {
00252 #ifdef RLWIN32
00253   return (int) CloseHandle((HANDLE) tid);
00254 #else
00255   return pthread_cancel(tid);
00256 #endif
00257 }
00258 
00259 /***********************************************/
00260 /* initialize a semaphore                      */
00261 /* s is a pointer to a WSEMAPHORE struct       */
00262 /* cmax is the maximum number of the semaphore */
00263 /* return 0                                    */
00264 /***********************************************/
00265 int rlwrapinit_semaphore(WSEMAPHORE *s, int cmax)
00266 {
00267 /* Create a semaphore with initial count=0 max. counts of cmax. */
00268 #ifdef RLWIN32
00269 
00270   s->cmax = cmax;
00271   s->hSemaphore = CreateSemaphore(
00272     NULL,   /* no security attributes */
00273     0,      /* initial count */
00274     cmax,   /* maximum count */
00275     NULL);  /* unnamed semaphore */
00276 
00277   if(s->hSemaphore == NULL) return -1; /* Check for error. */
00278   return 0;
00279 
00280 #else
00281 
00282   s->cmax   = cmax;
00283   s->nready = 0;
00284   rlwthread_mutex_init(&s->mutex, NULL);
00285   pthread_cond_init(&s->cond, NULL);
00286   return 0;
00287 
00288 #endif
00289 }
00290 
00291 int rlwrapdestroy_semaphore(WSEMAPHORE *s)
00292 {
00293 #ifdef RLWIN32
00294   CloseHandle(s->hSemaphore);
00295 #else
00296   rlwthread_mutex_destroy(&s->mutex);
00297 #endif
00298   return 0;
00299 }
00300 
00301 /***********************************************************************/
00302 /* increment a semaphore                                               */
00303 /* s is a pointer to a WSEMAPHORE struct                               */
00304 /* the producer will call this function whenever new data is available */
00305 /* return 0=OK -1=error                                                */
00306 /***********************************************************************/
00307 int rlwrapincrement_semaphore(WSEMAPHORE *s)
00308 {
00309 /* Increment the count of the semaphore. */
00310 #ifdef RLWIN32
00311 
00312   if(!ReleaseSemaphore(
00313         s->hSemaphore,  /* handle of semaphore */
00314         1,              /* increase count by one */
00315         NULL) )         /* not interested in previous count */
00316   {
00317     return -1; /* Deal with the error. */
00318   }
00319   return 0;
00320 
00321 #else
00322 
00323   pthread_mutex_lock(&s->mutex);
00324   if(s->nready == 0) pthread_cond_signal(&s->cond);
00325   s->nready++;
00326   pthread_mutex_unlock(&s->mutex);
00327   return 0;
00328 
00329 #endif
00330 }
00331 
00332 /*********************************************************************************/
00333 /* wait for a semaphore                                                          */
00334 /* s is a pointer to a WSEMAPHORE struct                                         */
00335 /* the consumer will call this function to wait for new data to become available */
00336 /* return 0                                                                      */
00337 /*********************************************************************************/
00338 int rlwrapwait_semaphore(WSEMAPHORE *s)
00339 {
00340 #ifdef RLWIN32
00341 
00342   int ret;
00343   ret = WaitForSingleObject(
00344         s->hSemaphore,   /* handle of semaphore */
00345         INFINITE);       /* infinite time-out interval */
00346   if(ret) return 0;
00347   return 0;
00348 
00349 #else
00350 
00351   pthread_mutex_lock(&s->mutex);
00352   while(s->nready == 0)
00353   {
00354     pthread_cond_wait(&s->cond,&s->mutex);
00355   }  
00356   s->nready--;
00357   pthread_mutex_unlock(&s->mutex);
00358   return 0;
00359 
00360 #endif
00361 }
00362 
00363 int rlwthread_sleep(long msec)
00364 {
00365 #ifdef RLWIN32
00366   Sleep(msec);
00367   return 0;
00368 #endif
00369 
00370 #ifdef RLUNIX
00371   fd_set wset,rset,eset;
00372   struct timeval timeout;
00373 
00374   FD_ZERO(&rset);
00375   FD_ZERO(&wset);
00376   FD_ZERO(&eset);
00377   timeout.tv_sec  = msec / 1000;
00378   timeout.tv_usec = (msec % 1000) * 1000;
00379   select(1,&rset,&wset,&eset,&timeout);
00380   return 0;
00381 #endif
00382 
00383 #ifdef __VMS
00384   struct timespec interval;
00385 
00386   interval.tv_sec  =  msec / 1000;
00387   interval.tv_nsec = (msec % 1000) * 1000 * 1000; /* wait msec msec */
00388   pthread_delay_np(&interval);
00389   return 0;
00390 #endif
00391 }
00392 
00393 void rlsleep(long msec)
00394 {
00395   rlwthread_sleep(msec);
00396 }
00397 /*** test routine ***/
00398 /**************************************************************/
00399 /* This is an example how to use the wthread_xxx functions    */
00400 /**************************************************************/
00401 #define TESTINGx
00402 #ifdef  TESTING
00403 #include "stdio.h"
00404 #include "stdlib.h"
00405 #ifndef RLWIN32
00406 #include "unistd.h"
00407 #endif
00408 
00409 /******************************************/
00410 /* here we define 2 mutexes (semaphores)  */
00411 /* the mutexes are global two all threads */
00412 /******************************************/
00413 pthread_mutex_t mutex1, mutex2;
00414 WSEMAPHORE semaphore;
00415 
00416 /************************************************************************/
00417 /* this is the tread function                                           */
00418 /* it's name is given as parameter to wthread_create                    */
00419 /* *arg is an argument given by the last parameter of wthread_create    */
00420 /* you can get the return value by pthread_join (status)                */
00421 /************************************************************************/
00422 void *thread(void *arg)
00423 {
00424   int i=0;
00425   printf("thread start : %s\n",(const char *) arg);
00426   while(i++ < 50)
00427   {
00428     rlwrapwait_semaphore(&semaphore);
00429     printf("thread %d\n",i);
00430     /* sleep(1); */
00431   }
00432   return NULL;
00433 }
00434 
00435 int main()
00436 {
00437   pthread_t tid; /* this is the thread_id */
00438   void *status;  /* this is the return value of the tread */
00439   int i;
00440 
00441   /*****************************************************************************/
00442   /* here we initialize 2 mutexes                                              */
00443   /* the mutexes are defined global to all threads                             */
00444   /* for compatibility with MSWINDOWS the second parameter should be NULL      */
00445   /*                                                                           */
00446   /* in order to mark critical sections we can now use the following functions */
00447   /* wthread_mutex_lock                                                        */
00448   /* wthread_mutex_unlock                                                      */
00449   /* if a mutex is locked by a thread and an other thread is calling           */
00450   /* wthread_mutex_lock it will be blocked until the first thread calls        */
00451   /* the wthread_mutex_unlock function                                         */
00452   /*                                                                           */
00453   /* this function is the reverse of wthread_mutex_init                        */
00454   /* wthread_mutex_destroy                                                     */
00455   /*****************************************************************************/
00456   rlwthread_mutex_init(&mutex1, NULL);
00457   rlwthread_mutex_init(&mutex2, NULL);
00458 
00459   rlwrapinit_semaphore(&semaphore, 1000);
00460   printf("create a thread\n");
00461   /****************************************************************/
00462   /* this call will create a new thread                           */
00463   /* tid is the returned thread_id                                */
00464   /*     you can use this id for example in wthread_join          */
00465   /* in this example the second parameter is NULL                 */
00466   /*     you can call wthread_attr_init(pthread_attr_t *attr)     */
00467   /*     to initialize the start attributes                       */
00468   /*     pthread_attr_t attr;                                     */
00469   /*     wthread_attr_init(&attr);                                */
00470   /*     wthread_create(&tid, &attr, thread, "hello thread");     */
00471   /* thread is the name of the thread function (see above)        */
00472   /* the last parameter is given to the thread function           */
00473   /****************************************************************/
00474   rlwthread_create(&tid, NULL, thread, "hello thread");
00475 
00476   i=0;
00477   while(i++ < 50)
00478   {
00479     printf("main %d\n",i);
00480     rlwrapincrement_semaphore(&semaphore);
00481     if(i%4 == 0) Sleep(10);
00482   }
00483 
00484   printf("waiting for thread\n");
00485   /*****************************************************/
00486   /* this call waits for the termination of thread tid */
00487   /* the return value of the thread is given to status */
00488   /*****************************************************/
00489   rlwthread_join(tid, &status);
00490   printf("finish\n");
00491   return 0;
00492 }
00493 #endif
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Defines