Skip to content

Instantly share code, notes, and snippets.

@wesen
Created January 10, 2013 11:45
Show Gist options
  • Select an option

  • Save wesen/4501463 to your computer and use it in GitHub Desktop.

Select an option

Save wesen/4501463 to your computer and use it in GitHub Desktop.
#ifndef MUTEX_H__
#define MUTEX_H__
#include "common.h"
#include <wirish/wirish_time.h>
/**
* Simple atomic swap memory mutex
*/
class Mutex {
private:
volatile unsigned char lock;
public:
Mutex(): lock(0) {
}
bool acquire() {
return __sync_bool_compare_and_swap(&lock, 0, 1);
}
bool acquireWait(uint32_t waitUs = 10, uint32_t timeoutUs = 0) {
uint32_t _timeout;
while (timeoutUs == 0 || _timeout < timeoutUs) {
if (acquire()) {
return true;
}
delayMicroseconds(timeoutUs);
_timeout += waitUs;
}
return false;
}
void release() {
// do we need the synchronized variant here? we can assume we are locked ?? XXX
lock = 0;
}
bool isLocked() {
return lock == 1;
}
};
/**
* blocking RAII mutex getter
*/
class MutexResource {
protected:
Mutex *mutex;
public:
MutexResource(Mutex *_m) : mutex(_m) {
mutex->acquire();
}
bool isLocked() {
return mutex->isLocked();
}
virtual ~MutexResource() {
mutex->release();
}
};
class MutexResourceWait {
protected:
Mutex *mutex;
public:
MutexResourceWait(Mutex *_m, uint32_t waitUs = 10, uint32_t timeoutUs = 0) : mutex(_m) {
mutex->acquireWait(waitUs, timeoutUs);
}
bool isLocked() {
return mutex->isLocked();
}
virtual ~MutexResourceWait() {
mutex->release();
}
};
/**
* Mutex protecting a resource
*/
template<typename T> class ResourceMutex : public Mutex {
private:
T resource;
public:
ResourceMutex() : Mutex() {
}
ResourceMutex(T init) : Mutex(), resource(init) {
}
volatile T *getResource() {
if (acquire()) {
return &resource;
} else {
return NULL;
}
}
volatile T *getResourceWait(uint32_t waitUs = 10, uint32_t timeoutUs = 0) {
if (acquireWait(waitUs, timeoutUs)) {
return &resource;
} else {
return NULL;
}
}
};
/**
* RAII style allocators
*/
template<typename T> class ResourceMutexResource {
protected:
ResourceMutex<T> *mutex;
public:
volatile T *resource;
ResourceMutexResource(ResourceMutex<T> *_m) : mutex(_m) {
resource = mutex->getResource();
}
virtual ~ResourceMutexResource() {
if (resource != NULL) {
mutex->release();
}
}
};
template<typename T> class ResourceMutexResourceWait {
protected:
ResourceMutex<T> *mutex;
public:
volatile T *resource;
ResourceMutexResourceWait(ResourceMutex<T> *_m, uint32_t waitUs = 10, uint32_t timeoutUs = 0) : mutex(_m) {
resource = mutex->getResourceWait(waitUs, timeoutUs);
}
virtual ~ResourceMutexResourceWait() {
if (resource != NULL) {
mutex->release();
}
}
};
#endif /* MUTEX_H__ */
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment