Rev 270 | Blame | Compare with Previous | Last modification | View Log | SVN | RSS feed
/***************************************************************************wthread.c - description-------------------begin : Sun Jan 02 2000copyright : (C) 2001 by Rainer Lehrigemail : lehrig@t-online.de***************************************************************************//**************************************************************************** ** This library is free software; you can redistribute it and/or modify ** it under the terms of the GNU LESSER GENERAL PUBLIC LICENSE as ** published by the Free Software Foundation ** ****************************************************************************//***********************************************************************************Wrapper for posix threads (UNIX,VMS,windows)(C) Rainer Lehrig 2000 lehrig@t-online.de***********************************************************************************/#include <errno.h>#include "rlwthread.h"#ifdef unix#include <sys/time.h>#include <sys/socket.h>#include <netinet/in.h>#include <netdb.h>#include <pthread.h>#endif/***************************************//* init attributes with default values *//***************************************/int rlwthread_attr_init(pthread_attr_t *attr){#ifdef _WIN32memset(attr,0,sizeof(pthread_attr_t));return 0;#elsereturn pthread_attr_init(attr);#endif}/* #pdoku headerlevel 2 ^^wthread_create *//*******************************************//* create a thread *//* tid: returned thread_id *//* attr: thread creation attributes *//* func: thread start routine *//* arg: parameter to thread start routine *//*******************************************/int rlwthread_create(pthread_t *tid, const pthread_attr_t *attr,void *(*func)(void*), void *arg){#ifdef _WIN32HANDLE handle;int ThreadId;int dwStackSize = 0;if(attr != NULL) dwStackSize = attr->__stacksize;handle = CreateThread( NULL, /* pointer to thread security attributes */dwStackSize, /* initial thread stack size, in bytes */(LPTHREAD_START_ROUTINE)func, /* pointer to thread function */arg, /* argument for new thread */0, /* creation flags */(unsigned long *) &ThreadId /* pointer to returned thread identifier */);*tid = (pthread_t) handle;if(handle == NULL) return -1;else return 0;#elsereturn pthread_create(tid,attr,func,arg);#endif}void rlwthread_close_handle(pthread_t *tid){#ifdef _WIN32CloseHandle((HANDLE) *tid);#elseif(tid == NULL) return;#endif}/**************************************************************//* terminate a thread *//* call this function within a thread to terminate the thead *//* or return from the thread start routine *//* status: return value from the thread (see wthread_join) *//**************************************************************/void rlwthread_exit(void *status){#ifdef _WIN32DWORD *ptr;ptr = (DWORD *) status;if(status == NULL) ExitThread((DWORD) 0);else ExitThread(*ptr);#elsepthread_exit(status);#endif}/* #pdoku headerlevel 2 ^^wthread_join *//************************************//* wait for termination of thread *//* tid: thread id *//* status: return value from thread *//************************************/int rlwthread_join(pthread_t tid, void **status){#ifdef _WIN32DWORD exitcode;while(1){GetExitCodeThread((HANDLE) tid,&exitcode);if(exitcode != STILL_ACTIVE) return exitcode;Sleep(10); /* sleep 10 msec */}#elsereturn pthread_join(tid,status);#endif}/**************************//* init a mutex *//* mptr: pointer to mutex *//* atrr: mutex atrributes *//**************************/int rlwthread_mutex_init(pthread_mutex_t *mptr,const pthread_mutexattr_t *attr){#ifdef _WIN32HANDLE handle = CreateMutex(NULL, FALSE, NULL);if(handle) *mptr = handle;//old InitializeCriticalSection(mptr);return 0;#elsereturn pthread_mutex_init(mptr,attr);#endif}/**************************//* destroy a mutex *//* mptr: pointer to mutex *//**************************/int rlwthread_mutex_destroy(pthread_mutex_t *mptr){#ifdef _WIN32CloseHandle(*mptr);//old DeleteCriticalSection(mptr);return 0;#elsereturn pthread_mutex_destroy(mptr);#endif}/**************************//* lock a mutex *//* mptr: pointer to mutex *//**************************/int rlwthread_mutex_lock(pthread_mutex_t *mptr){#ifdef _WIN32if(WaitForSingleObject(*mptr, INFINITE) == WAIT_OBJECT_0) return 0;//old EnterCriticalSection(mptr); // pointer to critical section objectreturn 0;#elsereturn pthread_mutex_lock(mptr);#endif}/********************************//* try to lock a mutex *//* mptr: pointer to mutex *//* return 0 if already locked *//* return !0 if lock sucessfull *//********************************/#ifdef _WIN32WINBASEAPI BOOL WINAPI TryEnterCriticalSection( LPCRITICAL_SECTION lpCriticalSection);#endifint rlwthread_mutex_trylock(pthread_mutex_t *mptr){#ifdef _WIN32DWORD ret;ret = WaitForSingleObject(*mptr, 0);if(ret == WAIT_OBJECT_0) return 1;return 0;//old ret = TryEnterCriticalSection(mptr); // pointer to critical section objectreturn ret;#elseint ret;ret = pthread_mutex_trylock(mptr);if(ret == EBUSY) return 0;return 1;#endif}/**************************//* unlock a mutex *//* mptr: pointer to mutex *//**************************/int rlwthread_mutex_unlock(pthread_mutex_t *mptr){#ifdef _WIN32ReleaseMutex(*mptr);//old LeaveCriticalSection(mptr);return 0;#elsereturn pthread_mutex_unlock(mptr);#endif}/**************************//* kill a thread *//* tid handel of thread *//**************************/int rlwthread_cancel(pthread_t tid){#ifdef _WIN32return (int) CloseHandle((HANDLE) tid);#elsereturn pthread_cancel(tid);#endif}/***********************************************//* initialize a semaphore *//* s is a pointer to a WSEMAPHORE struct *//* cmax is the maximum number of the semaphore *//* return 0 *//***********************************************/int rlwrapinit_semaphore(WSEMAPHORE *s, int cmax){/* Create a semaphore with initial count=0 max. counts of cmax. */#ifdef _WIN32s->cmax = cmax;s->hSemaphore = CreateSemaphore(NULL, /* no security attributes */0, /* initial count */cmax, /* maximum count */NULL); /* unnamed semaphore */if(s->hSemaphore == NULL) return -1; /* Check for error. */return 0;#elses->cmax = cmax;s->nready = 0;rlwthread_mutex_init(&s->mutex, NULL);pthread_cond_init(&s->cond, NULL);return 0;#endif}int rlwrapdestroy_semaphore(WSEMAPHORE *s){#ifdef _WIN32CloseHandle(s->hSemaphore);#elserlwthread_mutex_destroy(&s->mutex);#endifreturn 0;}/***********************************************************************//* increment a semaphore *//* s is a pointer to a WSEMAPHORE struct *//* the producer will call this function whenever new data is available *//* return 0=OK -1=error *//***********************************************************************/int rlwrapincrement_semaphore(WSEMAPHORE *s){/* Increment the count of the semaphore. */#ifdef _WIN32if(!ReleaseSemaphore(s->hSemaphore, /* handle of semaphore */1, /* increase count by one */NULL) ) /* not interested in previous count */{return -1; /* Deal with the error. */}return 0;#elsepthread_mutex_lock(&s->mutex);if(s->nready == 0) pthread_cond_signal(&s->cond);s->nready++;pthread_mutex_unlock(&s->mutex);return 0;#endif}/*********************************************************************************//* wait for a semaphore *//* s is a pointer to a WSEMAPHORE struct *//* the consumer will call this function to wait for new data to become available *//* return 0 *//*********************************************************************************/int rlwrapwait_semaphore(WSEMAPHORE *s){#ifdef _WIN32int ret;ret = WaitForSingleObject(s->hSemaphore, /* handle of semaphore */INFINITE); /* infinite time-out interval */if(ret) return 0;return 0;#elsepthread_mutex_lock(&s->mutex);while(s->nready == 0){pthread_cond_wait(&s->cond,&s->mutex);}s->nready--;pthread_mutex_unlock(&s->mutex);return 0;#endif}int rlwthread_sleep(long msec){#ifdef _WIN32Sleep(msec);return 0;#endif#ifdef unixfd_set wset,rset,eset;struct timeval timeout;FD_ZERO(&rset);FD_ZERO(&wset);FD_ZERO(&eset);timeout.tv_sec = msec / 1000;timeout.tv_usec = (msec % 1000) * 1000;select(1,&rset,&wset,&eset,&timeout);return 0;#endif#ifdef __VMSstruct timespec interval;interval.tv_sec = msec / 1000;interval.tv_nsec = (msec % 1000) * 1000 * 1000; /* wait msec msec */pthread_delay_np(&interval);return 0;#endif}void rlsleep(long msec){rlwthread_sleep(msec);}/*** test routine ***//**************************************************************//* This is an example how to use the wthread_xxx functions *//**************************************************************/#define TESTINGx#ifdef TESTING#include "stdio.h"#include "stdlib.h"#ifndef _WIN32#include "unistd.h"#endif/******************************************//* here we define 2 mutexes (semaphores) *//* the mutexes are global two all threads *//******************************************/pthread_mutex_t mutex1, mutex2;WSEMAPHORE semaphore;/************************************************************************//* this is the tread function *//* it's name is given as parameter to wthread_create *//* *arg is an argument given by the last parameter of wthread_create *//* you can get the return value by pthread_join (status) *//************************************************************************/void *thread(void *arg){int i=0;printf("thread start : %s\n",(const char *) arg);while(i++ < 50){rlwrapwait_semaphore(&semaphore);printf("thread %d\n",i);/* sleep(1); */}return NULL;}int main(){pthread_t tid; /* this is the thread_id */void *status; /* this is the return value of the tread */int i;/*****************************************************************************//* here we initialize 2 mutexes *//* the mutexes are defined global to all threads *//* for compatibility with MSWINDOWS the second parameter should be NULL *//* *//* in order to mark critical sections we can now use the following functions *//* wthread_mutex_lock *//* wthread_mutex_unlock *//* if a mutex is locked by a thread and an other thread is calling *//* wthread_mutex_lock it will be blocked until the first thread calls *//* the wthread_mutex_unlock function *//* *//* this function is the reverse of wthread_mutex_init *//* wthread_mutex_destroy *//*****************************************************************************/rlwthread_mutex_init(&mutex1, NULL);rlwthread_mutex_init(&mutex2, NULL);rlwrapinit_semaphore(&semaphore, 1000);printf("create a thread\n");/****************************************************************//* this call will create a new thread *//* tid is the returned thread_id *//* you can use this id for example in wthread_join *//* in this example the second parameter is NULL *//* you can call wthread_attr_init(pthread_attr_t *attr) *//* to initialize the start attributes *//* pthread_attr_t attr; *//* wthread_attr_init(&attr); *//* wthread_create(&tid, &attr, thread, "hello thread"); *//* thread is the name of the thread function (see above) *//* the last parameter is given to the thread function *//****************************************************************/rlwthread_create(&tid, NULL, thread, "hello thread");i=0;while(i++ < 50){printf("main %d\n",i);rlwrapincrement_semaphore(&semaphore);if(i%4 == 0) Sleep(10);}printf("waiting for thread\n");/*****************************************************//* this call waits for the termination of thread tid *//* the return value of the thread is given to status *//*****************************************************/rlwthread_join(tid, &status);printf("finish\n");return 0;}#endif