|
rllib
1
|
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
1.7.5.1