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