#pragma once
#ifndef __AUTO_LOCK__
#define __AUTO_LOCK__
#include <assert.h>
#include "Definitions.h"
#include "auto_impl_utilities.h"
namespace Auto {
struct LockedBoolean {
volatile bool state;
spin_lock_t lock;
LockedBoolean() : state(false), lock(0) {}
};
class SpinLock {
spin_lock_t *_lock;
public:
SpinLock(spin_lock_t *lock) : _lock(lock) { spin_lock(_lock); }
~SpinLock() { spin_unlock(_lock); }
};
class TrySpinLock {
spin_lock_t *_lock;
public:
TrySpinLock(spin_lock_t *lock) : _lock(lock) { if (_lock && !spin_lock_try(_lock)) _lock = NULL; }
operator int() { return (_lock != NULL); }
~TrySpinLock() { if (_lock) spin_unlock(_lock); }
};
class ConditionBarrier {
private:
spin_lock_t *_lock;
void check(bool volatile *condition, spin_lock_t *lock) {
if (*condition) {
spin_lock(lock);
if (!*condition) {
spin_unlock(lock);
} else {
_lock = lock;
}
}
}
public:
ConditionBarrier(bool volatile *condition, spin_lock_t *lock) : _lock(NULL) {
check(condition, lock);
}
ConditionBarrier(LockedBoolean &condition) : _lock(NULL) {
check(&condition.state, &condition.lock);
}
operator int() { return _lock != NULL; }
~ConditionBarrier() { if (_lock) spin_unlock(_lock); }
};
class UnconditionalBarrier {
bool volatile *_condition;
spin_lock_t *_lock;
public:
UnconditionalBarrier(bool volatile *condition, spin_lock_t *lock) : _condition(condition), _lock(lock) {
spin_lock(_lock);
}
UnconditionalBarrier(LockedBoolean &condition) : _condition(&condition.state), _lock(&condition.lock) {
spin_lock(_lock);
}
operator int() { return (*_condition != false); }
~UnconditionalBarrier() { spin_unlock(_lock); }
};
class Mutex {
pthread_mutex_t *_mutex;
public:
Mutex(pthread_mutex_t *mutex) : _mutex(mutex) { if (_mutex) pthread_mutex_lock(_mutex); }
~Mutex() { if (_mutex) pthread_mutex_unlock(_mutex); }
};
class TryMutex {
pthread_mutex_t *_mutex;
public:
TryMutex(pthread_mutex_t *mutex) : _mutex(mutex) { if (_mutex && pthread_mutex_trylock(_mutex) != 0) _mutex = NULL; }
operator int() { return (_mutex != NULL); }
~TryMutex() { if (_mutex) pthread_mutex_unlock(_mutex); }
};
class ReadLock {
pthread_rwlock_t *_lock;
public:
ReadLock(pthread_rwlock_t *lock) : _lock(lock) { if (_lock) pthread_rwlock_rdlock(_lock); }
~ReadLock() { if (_lock) pthread_rwlock_unlock(_lock); }
};
class WriteLock {
pthread_rwlock_t *_lock;
public:
WriteLock(pthread_rwlock_t *lock) : _lock(lock) { if (_lock) pthread_rwlock_wrlock(_lock); }
~WriteLock() { if (_lock) pthread_rwlock_unlock(_lock); }
};
class TryWriteLock {
pthread_rwlock_t *_lock;
public:
TryWriteLock(pthread_rwlock_t *lock) : _lock(lock) { if (_lock && pthread_rwlock_trywrlock(_lock) != 0) _lock = NULL; }
operator int() { return (_lock != NULL); }
~TryWriteLock() { if (_lock) pthread_rwlock_unlock(_lock); }
};
typedef uint32_t sentinel_t;
#define SENTINEL_T_INITIALIZER 0
class Sentinel {
sentinel_t &_guard;
public:
Sentinel(sentinel_t &guard) : _guard(guard) {
_guard++;
}
~Sentinel() { _guard--; }
inline static boolean_t is_guarded(sentinel_t &guard) { return guard != 0; }
inline static void assert_guarded(sentinel_t &guard) { assert(is_guarded(guard)); }
};
};
#endif // __AUTO_LOCK__