added mutex && cond var abstraction ( for pthread / winapi )
added type 'sysint' to cbasetypes, which's the width of the platform the release gets compiled for. git-svn-id: https://svn.code.sf.net/p/rathena/svn/trunk@16256 54d463be-8e91-2dee-dedb-b68131a5f0ec
This commit is contained in:
parent
f4b8626e7c
commit
12b9fdab9c
@ -3,7 +3,7 @@ COMMON_OBJ = obj_all/core.o obj_all/socket.o obj_all/timer.o obj_all/db.o obj_al
|
||||
obj_all/nullpo.o obj_all/malloc.o obj_all/showmsg.o obj_all/strlib.o obj_all/utils.o \
|
||||
obj_all/grfio.o obj_all/mapindex.o obj_all/ers.o obj_all/md5calc.o \
|
||||
obj_all/minicore.o obj_all/minisocket.o obj_all/minimalloc.o obj_all/random.o obj_all/des.o \
|
||||
obj_all/conf.o obj_all/thread.o
|
||||
obj_all/conf.o obj_all/thread.o obj_all/mutex.o
|
||||
|
||||
COMMON_H = $(shell ls ../common/*.h)
|
||||
|
||||
|
@ -197,6 +197,30 @@ typedef intptr_t intptr;
|
||||
typedef uintptr_t uintptr;
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Add a 'sysint' Type which has the width of the platform we're compiled for.
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
#if defined(__GNUC__)
|
||||
#if defined(__x86_64__)
|
||||
typedef int64 sysint;
|
||||
typedef uint64 usysint;
|
||||
#else
|
||||
typedef int32 sysint;
|
||||
typedef uint32 usysint;
|
||||
#endif
|
||||
#elif defined(_MSC_VER)
|
||||
#if defined(_M_X64)
|
||||
typedef int64 sysint;
|
||||
typedef uint64 usysint;
|
||||
#else
|
||||
typedef int32 sysint;
|
||||
typedef uint32 usysint;
|
||||
#endif
|
||||
#else
|
||||
#error Compiler / Platform is unsupported.
|
||||
#endif
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// some redefine of function redefines for some Compilers
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
244
src/common/mutex.c
Normal file
244
src/common/mutex.c
Normal file
@ -0,0 +1,244 @@
|
||||
|
||||
#ifdef WIN32
|
||||
#include "../common/winapi.h"
|
||||
#else
|
||||
#include <pthread.h>
|
||||
#include <time.h>
|
||||
#include <sys/time.h>
|
||||
#endif
|
||||
|
||||
#include "../common/cbasetypes.h"
|
||||
#include "../common/malloc.h"
|
||||
#include "../common/showmsg.h"
|
||||
#include "../common/timer.h"
|
||||
#include "../common/mutex.h"
|
||||
|
||||
struct ramutex{
|
||||
#ifdef WIN32
|
||||
CRITICAL_SECTION hMutex;
|
||||
#else
|
||||
pthread_mutex_t hMutex;
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
struct racond{
|
||||
#ifdef WIN32
|
||||
HANDLE events[2];
|
||||
ra_align(8) volatile LONG nWaiters;
|
||||
CRITICAL_SECTION waiters_lock;
|
||||
|
||||
#define EVENT_COND_SIGNAL 0
|
||||
#define EVENT_COND_BROADCAST 1
|
||||
|
||||
#else
|
||||
pthread_cond_t hCond;
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
////////////////////
|
||||
// Mutex
|
||||
//
|
||||
// Implementation:
|
||||
//
|
||||
|
||||
|
||||
ramutex ramutex_create(){
|
||||
struct ramutex *m;
|
||||
|
||||
m = (struct ramutex*)aMalloc( sizeof(struct ramutex) );
|
||||
if(m == NULL){
|
||||
ShowFatalError("ramutex_create: OOM while allocating %u bytes.\n", sizeof(struct ramutex));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#ifdef WIN32
|
||||
InitializeCriticalSection(&m->hMutex);
|
||||
#else
|
||||
pthread_mutex_init(&m->hMutex, NULL);
|
||||
#endif
|
||||
|
||||
return m;
|
||||
}//end: ramutex_create()
|
||||
|
||||
|
||||
void ramutex_destroy( ramutex m ){
|
||||
|
||||
#ifdef WIN32
|
||||
DeleteCriticalSection(&m->hMutex);
|
||||
#else
|
||||
pthread_mutex_destroy(&m->hMutex);
|
||||
#endif
|
||||
|
||||
aFree(m);
|
||||
|
||||
}//end: ramutex_destroy()
|
||||
|
||||
|
||||
void ramutex_lock( ramutex m ){
|
||||
|
||||
#ifdef WIN32
|
||||
EnterCriticalSection(&m->hMutex);
|
||||
#else
|
||||
pthread_mutex_lock(&m->hMutex);
|
||||
#endif
|
||||
}//end: ramutex_lock
|
||||
|
||||
|
||||
bool ramutex_trylock( ramutex m ){
|
||||
#ifdef WIN32
|
||||
if(TryEnterCriticalSection(&m->hMutex) == TRUE)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
#else
|
||||
if(pthread_mutex_trylock(&m->hMutex) == 0)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
#endif
|
||||
}//end: ramutex_trylock()
|
||||
|
||||
|
||||
void ramutex_unlock( ramutex m ){
|
||||
#ifdef WIN32
|
||||
LeaveCriticalSection(&m->hMutex);
|
||||
#else
|
||||
pthread_mutex_unlock(&m->hMutex);
|
||||
#endif
|
||||
|
||||
}//end: ramutex_unlock()
|
||||
|
||||
|
||||
|
||||
///////////////
|
||||
// Condition Variables
|
||||
//
|
||||
// Implementation:
|
||||
//
|
||||
|
||||
racond racond_create(){
|
||||
struct racond *c;
|
||||
|
||||
c = (struct racond*)aMalloc( sizeof(struct racond) );
|
||||
if(c == NULL){
|
||||
ShowFatalError("racond_create: OOM while allocating %u bytes\n", sizeof(struct racond));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#ifdef WIN32
|
||||
c->nWaiters = 0;
|
||||
c->events[ EVENT_COND_SIGNAL ] = CreateEvent( NULL, FALSE, FALSE, NULL );
|
||||
c->events[ EVENT_COND_BROADCAST ] = CreateEvent( NULL, TRUE, FALSE, NULL );
|
||||
#else
|
||||
pthread_cond_init(&c->hCond, NULL);
|
||||
#endif
|
||||
|
||||
return c;
|
||||
}//end: racond_create()
|
||||
|
||||
|
||||
void racond_destroy( racond c ){
|
||||
#ifdef WIN32
|
||||
CloseHandle( c->events[ EVENT_COND_SIGNAL ] );
|
||||
CloseHandle( c->events[ EVENT_COND_BROADCAST ] );
|
||||
InitializeCriticalSection( &c->waiters_lock );
|
||||
#else
|
||||
pthread_cond_destroy(&c->hCond);
|
||||
#endif
|
||||
|
||||
aFree(c);
|
||||
}//end: racond_destroy()
|
||||
|
||||
|
||||
void racond_wait( racond c, ramutex m, sysint timeout_ticks){
|
||||
#ifdef WIN32
|
||||
register DWORD ms;
|
||||
int result;
|
||||
bool is_last = false;
|
||||
|
||||
|
||||
EnterCriticalSection(&c->waiters_lock);
|
||||
c->nWaiters++;
|
||||
LeaveCriticalSection(&c->waiters_lock);
|
||||
|
||||
if(timeout_ticks < 0)
|
||||
ms = INFINITE;
|
||||
else
|
||||
ms = (timeout_ticks > MAXDWORD) ? (MAXDWORD - 1) : (DWORD)timeout_ticks;
|
||||
|
||||
|
||||
// we can release the mutex (m) here, cause win's
|
||||
// manual reset events maintain state when used with
|
||||
// SetEvent()
|
||||
ramutex_unlock(m);
|
||||
|
||||
result = WaitForMultipleObjects(2, c->events, FALSE, ms);
|
||||
|
||||
|
||||
EnterCriticalSection(&c->waiters_lock);
|
||||
c->nWaiters--;
|
||||
if( (result == WAIT_OBJECT_0 + EVENT_COND_BROADCAST) && (c->nWaiters == 0) )
|
||||
is_last = true; // Broadcast called!
|
||||
LeaveCriticalSection(&c->waiters_lock);
|
||||
|
||||
|
||||
|
||||
// we are the last waiter that has to be notified, or to stop waiting
|
||||
// so we have to do a manual reset
|
||||
if(is_last == true)
|
||||
ResetEvent( c->events[EVENT_COND_BROADCAST] );
|
||||
|
||||
|
||||
ramutex_lock(m);
|
||||
|
||||
#else
|
||||
if(timeout_ticks < 0){
|
||||
pthread_cond_wait( &c->hCond, &m->hMutex );
|
||||
}else{
|
||||
struct timespec wtime;
|
||||
int64 exact_timeout = gettick() + timeout_ticks;
|
||||
|
||||
wtime.tv_sec = exact_timeout/1000;
|
||||
wtime.tv_nsec = (exact_timeout%1000)*1000000;
|
||||
|
||||
pthread_cond_timedwait( &c->hCond, &m->hMutex, &wtime);
|
||||
}
|
||||
|
||||
#endif
|
||||
}//end: racond_wait()
|
||||
|
||||
|
||||
void racond_signal( racond c ){
|
||||
#ifdef WIN32
|
||||
// bool has_waiters = false;
|
||||
// EnterCriticalSection(&c->waiters_lock);
|
||||
// if(c->nWaiters > 0)
|
||||
// has_waiters = true;
|
||||
// LeaveCriticalSection(&c->waiters_lock);
|
||||
|
||||
// if(has_waiters == true)
|
||||
SetEvent( c->events[ EVENT_COND_SIGNAL ] );
|
||||
#else
|
||||
pthread_cond_signal(&c->hCond);
|
||||
#endif
|
||||
}//end: racond_signal()
|
||||
|
||||
|
||||
void racond_broadcast( racond c ){
|
||||
#ifdef WIN32
|
||||
// bool has_waiters = false;
|
||||
// EnterCriticalSection(&c->waiters_lock);
|
||||
// if(c->nWaiters > 0)
|
||||
// has_waiters = true;
|
||||
// LeaveCriticalSection(&c->waiters_lock);
|
||||
|
||||
// if(has_waiters == true)
|
||||
SetEvent( c->events[ EVENT_COND_BROADCAST ] );
|
||||
#else
|
||||
pthread_cond_broadcast(&c->hCond);
|
||||
#endif
|
||||
}//end: racond_broadcast()
|
||||
|
||||
|
89
src/common/mutex.h
Normal file
89
src/common/mutex.h
Normal file
@ -0,0 +1,89 @@
|
||||
#ifndef _rA_MUTEX_H_
|
||||
#define _rA_MUTEX_H_
|
||||
|
||||
|
||||
typedef struct ramutex *ramutex; // Mutex
|
||||
typedef struct racond *racond; // Condition Var
|
||||
|
||||
/**
|
||||
* Creates a Mutex
|
||||
*
|
||||
* @return not NULL
|
||||
*/
|
||||
ramutex ramutex_create();
|
||||
|
||||
/**
|
||||
* Destroys a Mutex
|
||||
*
|
||||
* @param m - the mutex to destroy
|
||||
*/
|
||||
void ramutex_destroy( ramutex m );
|
||||
|
||||
/**
|
||||
* Gets a lock
|
||||
*
|
||||
* @param m - the mutex to lock
|
||||
*/
|
||||
void ramutex_lock( ramutex m);
|
||||
|
||||
/**
|
||||
* Trys to get the Lock
|
||||
*
|
||||
* @param m - the mutex try to lock
|
||||
*
|
||||
* @return boolean (true = got the lock)
|
||||
*/
|
||||
bool ramutex_trylock( ramutex m );
|
||||
|
||||
/**
|
||||
* Unlocks a mutex
|
||||
*
|
||||
* @param m - the mutex to unlock
|
||||
*/
|
||||
void ramutex_unlock( ramutex m);
|
||||
|
||||
|
||||
/**
|
||||
* Creates a Condition variable
|
||||
*
|
||||
* @return not NULL
|
||||
*/
|
||||
racond racond_create();
|
||||
|
||||
/**
|
||||
* Destroy a Condition variable
|
||||
*
|
||||
* @param c - the condition varaible to destroy
|
||||
*/
|
||||
void racond_destroy( racond c );
|
||||
|
||||
/**
|
||||
* Waits Until state is signalled
|
||||
*
|
||||
* @param c - the condition var to wait for signalled state
|
||||
* @param m - the mutex used for syncronization
|
||||
* @param timeout_ticks - timeout in ticks ( -1 = INFINITE )
|
||||
*/
|
||||
void racond_wait( racond c, ramutex m, sysint timeout_ticks);
|
||||
|
||||
/**
|
||||
* Sets the given condition var to signalled state
|
||||
*
|
||||
* @param c - condition var to set in signalled state.
|
||||
*
|
||||
* @note:
|
||||
* Only one waiter gets notified.
|
||||
*/
|
||||
void racond_signal( racond c );
|
||||
|
||||
/**
|
||||
* Sets notifys all waiting threads thats signalled.
|
||||
* @param c - condition var to set in signalled state
|
||||
*
|
||||
* @note:
|
||||
* All Waiters getting notified.
|
||||
*/
|
||||
void racond_broadcast( racond c );
|
||||
|
||||
|
||||
#endif
|
Loading…
x
Reference in New Issue
Block a user