Add a lock library
This commit is contained in:
parent
0bb278bcdd
commit
b617378430
37
lock/ConditionBarrier.h
Normal file
37
lock/ConditionBarrier.h
Normal file
@ -0,0 +1,37 @@
|
||||
#ifndef MESSMER_CPPUTILS_CONDITIONBARRIER_H
|
||||
#define MESSMER_CPPUTILS__CONDITIONBARRIER_H
|
||||
|
||||
#include <mutex>
|
||||
#include <condition_variable>
|
||||
|
||||
//TODO Test
|
||||
|
||||
namespace cpputils {
|
||||
// Like a condition variable, but without spurious wakeups.
|
||||
// The waiting threads are only woken, when notify() is called.
|
||||
// After a call to release(), future calls to wait() will not block anymore.
|
||||
class ConditionBarrier {
|
||||
public:
|
||||
ConditionBarrier() :_mutex(), _cv(), _triggered(false) {
|
||||
}
|
||||
|
||||
void wait() {
|
||||
std::unique_lock<std::mutex> lock(_mutex);
|
||||
_cv.wait(lock, [this] {
|
||||
return _triggered;
|
||||
});
|
||||
}
|
||||
|
||||
void release() {
|
||||
std::unique_lock<std::mutex> lock(_mutex);
|
||||
_triggered = true;
|
||||
_cv.notify_all();
|
||||
}
|
||||
private:
|
||||
std::mutex _mutex;
|
||||
std::condition_variable _cv;
|
||||
bool _triggered;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
1
lock/LockPool.cpp
Normal file
1
lock/LockPool.cpp
Normal file
@ -0,0 +1 @@
|
||||
#include "LockPool.h"
|
73
lock/LockPool.h
Normal file
73
lock/LockPool.h
Normal file
@ -0,0 +1,73 @@
|
||||
#ifndef MESSMER_CPPUTILS_LOCKPOOL_H
|
||||
#define MESSMER_CPPUTILS_LOCKPOOL_H
|
||||
|
||||
#include <mutex>
|
||||
#include <condition_variable>
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
#include "../assert/assert.h"
|
||||
#include "../macros.h"
|
||||
|
||||
//TODO Test
|
||||
//TODO Rename package to synchronization
|
||||
//TODO Rename to MutexPool
|
||||
namespace cpputils {
|
||||
template<class LockName>
|
||||
class LockPool {
|
||||
public:
|
||||
LockPool();
|
||||
void lock(const LockName &lock, std::unique_lock<std::mutex> *lockToFreeWhileWaiting = nullptr);
|
||||
void release(const LockName &lock);
|
||||
|
||||
private:
|
||||
bool _isLocked(const LockName &lock) const;
|
||||
|
||||
std::vector<LockName> _lockedLocks;
|
||||
std::mutex _mutex;
|
||||
std::condition_variable _cv;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(LockPool);
|
||||
};
|
||||
template<class LockName>
|
||||
inline LockPool<LockName>::LockPool(): _lockedLocks(), _mutex(), _cv() {}
|
||||
|
||||
template<class LockName>
|
||||
inline void LockPool<LockName>::lock(const LockName &lock, std::unique_lock<std::mutex> *lockToFreeWhileWaiting) {
|
||||
std::cerr << "Aquiring lock " << lock.ToString() << std::endl;
|
||||
std::unique_lock<std::mutex> mutexLock(_mutex); // TODO Is shared_lock enough here?
|
||||
std::cerr << (void*)this << " Bquiring lock " << lock.ToString() << std::endl;
|
||||
if (_isLocked(lock)) {
|
||||
std::cerr << " is locked " << lock.ToString() << std::endl;
|
||||
if(lockToFreeWhileWaiting != nullptr) {
|
||||
lockToFreeWhileWaiting->unlock();
|
||||
}
|
||||
_cv.wait(mutexLock, [this, &lock]{
|
||||
return !_isLocked(lock);
|
||||
});
|
||||
std::cerr << " reaquiring " << lock.ToString() << std::endl;
|
||||
if(lockToFreeWhileWaiting != nullptr) {
|
||||
lockToFreeWhileWaiting->lock();
|
||||
}
|
||||
}
|
||||
std::cerr << "Lock acquired " << lock.ToString() << std::endl;
|
||||
_lockedLocks.push_back(lock);
|
||||
}
|
||||
|
||||
template<class LockName>
|
||||
inline bool LockPool<LockName>::_isLocked(const LockName &lock) const {
|
||||
return std::find(_lockedLocks.begin(), _lockedLocks.end(), lock) != _lockedLocks.end();
|
||||
}
|
||||
|
||||
template<class LockName>
|
||||
inline void LockPool<LockName>::release(const LockName &lock) {
|
||||
std::cerr << "Releasing lock "<<lock.ToString()<<std::endl;
|
||||
std::unique_lock<std::mutex> mutexLock(_mutex);
|
||||
auto found = std::find(_lockedLocks.begin(), _lockedLocks.end(), lock);
|
||||
ASSERT(found != _lockedLocks.end(), "Lock given to release() was not locked");
|
||||
_lockedLocks.erase(found);
|
||||
_cv.notify_all();
|
||||
std::cerr << "Lock released "<<lock.ToString()<<std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
38
lock/MutexPoolLock.h
Normal file
38
lock/MutexPoolLock.h
Normal file
@ -0,0 +1,38 @@
|
||||
#ifndef MESSMER_CPPUTILS_LOCK_MUTEXPOOLLOCK_H
|
||||
#define MESSMER_CPPUTILS_LOCK_MUTEXPOOLLOCK_H
|
||||
|
||||
#include "LockPool.h"
|
||||
|
||||
namespace cpputils {
|
||||
template<class LockName>
|
||||
class MutexPoolLock {
|
||||
public:
|
||||
MutexPoolLock(LockPool<LockName> *pool, const LockName &lockName): _pool(pool), _lockName(lockName) {
|
||||
_pool->lock(_lockName);
|
||||
}
|
||||
|
||||
MutexPoolLock(LockPool<LockName> *pool, const LockName &lockName, std::unique_lock<std::mutex> *lockToFreeWhileWaiting)
|
||||
: _pool(pool), _lockName(lockName) {
|
||||
_pool->lock(_lockName, lockToFreeWhileWaiting);
|
||||
}
|
||||
|
||||
MutexPoolLock(MutexPoolLock &&rhs): _pool(rhs._pool), _lockName(rhs._lockName) {
|
||||
rhs._pool = nullptr;
|
||||
}
|
||||
|
||||
~MutexPoolLock() {
|
||||
if (_pool != nullptr) {
|
||||
_pool->release(_lockName);
|
||||
_pool = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
LockPool<LockName> *_pool;
|
||||
LockName _lockName;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(MutexPoolLock);
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue
Block a user