diff options
Diffstat (limited to 'src/common/mutex.c')
-rw-r--r-- | src/common/mutex.c | 158 |
1 files changed, 91 insertions, 67 deletions
diff --git a/src/common/mutex.c b/src/common/mutex.c index 0f02b153f..bdc2fb4dc 100644 --- a/src/common/mutex.c +++ b/src/common/mutex.c @@ -2,7 +2,7 @@ * This file is part of Hercules. * http://herc.ws - http://github.com/HerculesWS/Hercules * - * Copyright (C) 2012-2015 Hercules Dev Team + * Copyright (C) 2012-2016 Hercules Dev Team * Copyright (C) rAthena Project (www.rathena.org) * * Hercules is free software: you can redistribute it and/or modify @@ -34,7 +34,14 @@ #include <sys/time.h> #endif -struct ramutex{ +/** @file + * Implementation of the mutex interface. + */ + +struct mutex_interface mutex_s; +struct mutex_interface *mutex; + +struct mutex_data { #ifdef WIN32 CRITICAL_SECTION hMutex; #else @@ -42,32 +49,26 @@ struct ramutex{ #endif }; -struct racond{ +struct cond_data { #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: -// +/* Mutex */ -ramutex *ramutex_create(void) { - struct ramutex *m; - - m = (struct ramutex*)aMalloc( sizeof(struct ramutex) ); +/// @copydoc mutex_interface::create() +struct mutex_data *mutex_create(void) +{ + struct mutex_data *m = aMalloc(sizeof(struct mutex_data)); if (m == NULL) { - ShowFatalError("ramutex_create: OOM while allocating %"PRIuS" bytes.\n", sizeof(struct ramutex)); + ShowFatalError("ramutex_create: OOM while allocating %"PRIuS" bytes.\n", sizeof(struct mutex_data)); return NULL; } @@ -78,10 +79,11 @@ ramutex *ramutex_create(void) { #endif return m; -}//end: ramutex_create() - -void ramutex_destroy(ramutex *m) { +} +/// @copydoc mutex_interface::destroy() +void mutex_destroy(struct mutex_data *m) +{ #ifdef WIN32 DeleteCriticalSection(&m->hMutex); #else @@ -89,53 +91,49 @@ void ramutex_destroy(ramutex *m) { #endif aFree(m); +} -}//end: ramutex_destroy() - -void ramutex_lock(ramutex *m) { - +/// @copydoc mutex_interface::lock() +void mutex_lock(struct mutex_data *m) +{ #ifdef WIN32 EnterCriticalSection(&m->hMutex); #else pthread_mutex_lock(&m->hMutex); #endif -}//end: ramutex_lock +} -bool ramutex_trylock(ramutex *m) { +/// @copydoc mutex_interface::trylock() +bool mutex_trylock(struct mutex_data *m) +{ #ifdef WIN32 - if(TryEnterCriticalSection(&m->hMutex) != FALSE) + if (TryEnterCriticalSection(&m->hMutex) != FALSE) return true; - - return false; #else - if(pthread_mutex_trylock(&m->hMutex) == 0) + if (pthread_mutex_trylock(&m->hMutex) == 0) return true; - - return false; #endif -}//end: ramutex_trylock() + return false; +} -void ramutex_unlock(ramutex *m) { +/// @copydoc mutex_interface::unlock() +void mutex_unlock(struct mutex_data *m) +{ #ifdef WIN32 LeaveCriticalSection(&m->hMutex); #else pthread_mutex_unlock(&m->hMutex); #endif +} -}//end: ramutex_unlock() - -/////////////// -// Condition Variables -// -// Implementation: -// +/* Conditional variable */ -racond *racond_create(void) { - struct racond *c; - - c = (struct racond*)aMalloc( sizeof(struct racond) ); +/// @copydoc mutex_interface::cond_create() +struct cond_data *cond_create(void) +{ + struct cond_data *c = aMalloc(sizeof(struct cond_data)); if (c == NULL) { - ShowFatalError("racond_create: OOM while allocating %"PRIuS" bytes\n", sizeof(struct racond)); + ShowFatalError("racond_create: OOM while allocating %"PRIuS" bytes\n", sizeof(struct cond_data)); return NULL; } @@ -149,21 +147,25 @@ racond *racond_create(void) { #endif return c; -}//end: racond_create() +} -void racond_destroy(racond *c) { +/// @copydoc mutex_interface::cond_destroy() +void cond_destroy(struct cond_data *c) +{ #ifdef WIN32 - CloseHandle( c->events[ EVENT_COND_SIGNAL ] ); - CloseHandle( c->events[ EVENT_COND_BROADCAST ] ); - DeleteCriticalSection( &c->waiters_lock ); + CloseHandle(c->events[EVENT_COND_SIGNAL]); + CloseHandle(c->events[EVENT_COND_BROADCAST]); + DeleteCriticalSection(&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) { +/// @copydoc mutex_interface::cond_wait() +void cond_wait(struct cond_data *c, struct mutex_data *m, sysint timeout_ticks) +{ #ifdef WIN32 register DWORD ms; int result; @@ -173,7 +175,7 @@ void racond_wait(racond *c, ramutex *m, sysint timeout_ticks) { c->nWaiters++; LeaveCriticalSection(&c->waiters_lock); - if(timeout_ticks < 0) + if (timeout_ticks < 0) ms = INFINITE; else ms = (timeout_ticks > MAXDWORD) ? (MAXDWORD - 1) : (DWORD)timeout_ticks; @@ -181,27 +183,27 @@ void racond_wait(racond *c, ramutex *m, sysint timeout_ticks) { // we can release the mutex (m) here, cause win's // manual reset events maintain state when used with // SetEvent() - ramutex_unlock(m); + mutex->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) ) + 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) + if (is_last == true) ResetEvent( c->events[EVENT_COND_BROADCAST] ); - ramutex_lock(m); + mutex->lock(m); #else - if(timeout_ticks < 0){ - pthread_cond_wait( &c->hCond, &m->hMutex ); - }else{ + if (timeout_ticks < 0) { + pthread_cond_wait(&c->hCond, &m->hMutex); + } else { struct timespec wtime; int64 exact_timeout = timer->gettick() + timeout_ticks; @@ -210,11 +212,12 @@ void racond_wait(racond *c, ramutex *m, sysint timeout_ticks) { pthread_cond_timedwait( &c->hCond, &m->hMutex, &wtime); } - #endif -}//end: racond_wait() +} -void racond_signal(racond *c) { +/// @copydoc mutex_interface::cond_signal() +void cond_signal(struct cond_data *c) +{ #ifdef WIN32 # if 0 bool has_waiters = false; @@ -225,13 +228,15 @@ void racond_signal(racond *c) { if(has_waiters == true) # endif // 0 - SetEvent( c->events[ EVENT_COND_SIGNAL ] ); + SetEvent(c->events[EVENT_COND_SIGNAL]); #else pthread_cond_signal(&c->hCond); #endif -}//end: racond_signal() +} -void racond_broadcast(racond *c) { +/// @copydoc mutex_interface::cond_broadcast() +void cond_broadcast(struct cond_data *c) +{ #ifdef WIN32 # if 0 bool has_waiters = false; @@ -242,8 +247,27 @@ void racond_broadcast(racond *c) { if(has_waiters == true) # endif // 0 - SetEvent( c->events[ EVENT_COND_BROADCAST ] ); + SetEvent(c->events[EVENT_COND_BROADCAST]); #else pthread_cond_broadcast(&c->hCond); #endif -}//end: racond_broadcast() +} + +/** + * Interface base initialization. + */ +void mutex_defaults(void) +{ + mutex = &mutex_s; + mutex->create = mutex_create; + mutex->destroy = mutex_destroy; + mutex->lock = mutex_lock; + mutex->trylock = mutex_trylock; + mutex->unlock = mutex_unlock; + + mutex->cond_create = cond_create; + mutex->cond_destroy = cond_destroy; + mutex->cond_wait = cond_wait; + mutex->cond_signal = cond_signal; + mutex->cond_broadcast = cond_broadcast; +} |