locker.h
#pragma once
#ifdef _WIN32
#include <conio.h>
#include <windows.h>
#include <process.h>
#include <tlhelp32.h>
#include <sys/utime.h>
#include <io.h>
#include <direct.h>
#else
#include <assert.h>
#include <pthread.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
#endif
class Locker
{
public:
enum LOCK_STATUS {
LOCK_OK = 0,
LOCK_TIMEOUT = -1,
LOCK_FAILED = -2
};
Locker(){
#ifdef _WIN32
_lock = NULL;
#endif
init();
}
~Locker(){
release();
}
Locker::LOCK_STATUS lock(unsigned long timeout = 0xFFFFFFFF) {
#ifdef _WIN32
switch (WaitForSingleObject(_lock, timeout==0xFFFFFFF?INFINITE:(DWORD)timeout)) {
case WAIT_ABANDONED:
return LOCK_FAILED;
case WAIT_OBJECT_0:
return LOCK_OK;
case WAIT_TIMEOUT:
return LOCK_TIMEOUT;
}
#else
#ifdef _MACOS
if (timeout !=0 ) {
if (pthread_mutex_lock(&_lock) == 0) return LOCK_OK;
}
#else
if (timeout == 0xFFFFFFFF){
if (pthread_mutex_lock(&_lock) == 0) return LOCK_OK;
}
#endif
else if (timeout == 0) {
if (pthread_mutex_trylock(&_lock) == 0) return LOCK_OK;
}
#ifndef _MACOS
else{
timespec wait_time;
timeval now;
gettimeofday(&now,NULL);
wait_time.tv_sec = timeout/1000 + now.tv_sec;
wait_time.tv_nsec = (timeout%1000)*1000000 + now.tv_usec*1000;
if (wait_time.tv_nsec >= 1000000000){
++wait_time.tv_sec;
wait_time.tv_nsec -= 1000000000;
}
#if !defined(__ANDROID__)
switch (pthread_mutex_timedlock(&_lock,&wait_time)){
case 0:
return LOCK_OK;
case ETIMEDOUT:
return LOCK_TIMEOUT;
}
#else
struct timeval timenow;
struct timespec sleepytime;
/* This is just to avoid a completely busy wait */
sleepytime.tv_sec = 0;
sleepytime.tv_nsec = 10000000; /* 10ms */
while (pthread_mutex_trylock (&_lock) == EBUSY) {
gettimeofday (&timenow, NULL);
if (timenow.tv_sec >= wait_time.tv_sec &&
(timenow.tv_usec * 1000) >= wait_time.tv_nsec) {
return LOCK_TIMEOUT;
}
nanosleep (&sleepytime, NULL);
}
return LOCK_OK;
#endif
}
#endif
#endif
return LOCK_FAILED;
}
void unlock(){
#ifdef _WIN32
ReleaseMutex(_lock);
#else
pthread_mutex_unlock(&_lock);
#endif
}
#ifdef _WIN32
HANDLE getLockHandle(){
return _lock;
}
#else
pthread_mutex_t *getLockHandle(){
return &_lock;
}
#endif
protected:
void init(){
#ifdef _WIN32
_lock = CreateMutex(NULL,FALSE,NULL);
#else
pthread_mutex_init(&_lock, NULL);
#endif
}
void release(){
unlock();
#ifdef _WIN32
if(_lock){
CloseHandle(_lock);
}
_lock = NULL;
#else
pthread_mutex_destroy(&_lock);
#endif
}
#ifdef _WIN32
HANDLE _lock;
#else
pthread_mutex_t _lock;
#endif
};
class Event
{
public:
enum {
EVENT_OK = 1,
EVENT_TIMEOUT = 2,
EVENT_FAILED = 0,
};
explicit Event(bool isAutoReset = true, bool isSignal = false)
#ifdef _WIN32
: _event(NULL)
#else
: _is_signalled(isSignal)
, _isAutoReset(isAutoReset)
#endif
{
#ifdef _WIN32
_event = CreateEvent(NULL, isAutoReset?FALSE:TRUE, isSignal?TRUE:FALSE, NULL);
#else
pthread_mutex_init(&_cond_locker, NULL);
pthread_cond_init(&_cond_var, NULL);
#endif
}
~ Event(){
release();
}
void set( bool isSignal = true ){
if (isSignal){
#ifdef _WIN32
SetEvent(_event);
#else
pthread_mutex_lock(&_cond_locker);
if ( _is_signalled == false ){
_is_signalled = true;
pthread_cond_signal(&_cond_var);
}
pthread_mutex_unlock(&_cond_locker);
#endif
}else{
#ifdef _WIN32
ResetEvent(_event);
#else
pthread_mutex_lock(&_cond_locker);
_is_signalled = false;
pthread_mutex_unlock(&_cond_locker);
#endif
}
}
unsigned long wait( unsigned long timeout = 0xFFFFFFFF ){
#ifdef _WIN32
switch (WaitForSingleObject(_event, timeout==0xFFFFFFF?INFINITE:(DWORD)timeout)){
case WAIT_FAILED:
return EVENT_FAILED;
case WAIT_OBJECT_0:
return EVENT_OK;
case WAIT_TIMEOUT:
return EVENT_TIMEOUT;
}
return EVENT_OK;
#else
unsigned long ans = EVENT_OK;
pthread_mutex_lock( &_cond_locker );
if (!_is_signalled){
if (timeout == 0xFFFFFFFF){
pthread_cond_wait(&_cond_var,&_cond_locker);
}else{
timespec wait_time;
timeval now;
gettimeofday(&now,NULL);
wait_time.tv_sec = timeout/1000 + now.tv_sec;
wait_time.tv_nsec = (timeout%1000)*1000000ULL + now.tv_usec*1000;
if (wait_time.tv_nsec >= 1000000000){
++wait_time.tv_sec;
wait_time.tv_nsec -= 1000000000;
}
switch (pthread_cond_timedwait(&_cond_var,&_cond_locker,&wait_time)){
case 0:
// signalled
break;
case ETIMEDOUT:
// time up
ans = EVENT_TIMEOUT;
goto _final;
break;
default:
ans = EVENT_FAILED;
goto _final;
}
}
}
assert(_is_signalled);
if (_isAutoReset){
_is_signalled = false;
}
_final:
pthread_mutex_unlock( &_cond_locker );
return ans;
#endif
}
protected:
void release() {
#ifdef _WIN32
CloseHandle(_event);
#else
pthread_mutex_destroy(&_cond_locker);
pthread_cond_destroy(&_cond_var);
#endif
}
#ifdef _WIN32
HANDLE _event;
#else
pthread_cond_t _cond_var;
pthread_mutex_t _cond_locker;
bool _is_signalled;
bool _isAutoReset;
#endif
};
class ScopedLocker
{
public :
explicit ScopedLocker(Locker &l): _binded(l) {
_binded.lock();
}
void forceUnlock() {
_binded.unlock();
}
~ScopedLocker() {
_binded.unlock();
}
Locker & _binded;
};
Event
Definition: locker.h:167
ScopedLocker
Definition: locker.h:301
Locker
Definition: locker.h:20