mirror of
https://github.com/privatevoid-net/nix-super.git
synced 2024-11-22 14:06:16 +02:00
Sync: Add support for shared locks
This commit is contained in:
parent
b0283240a1
commit
2f39caf180
1 changed files with 40 additions and 13 deletions
|
@ -3,6 +3,7 @@
|
||||||
|
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
|
#include <shared_mutex>
|
||||||
#include <condition_variable>
|
#include <condition_variable>
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
|
||||||
|
@ -24,8 +25,8 @@ namespace nix {
|
||||||
* Here, "data" is automatically unlocked when "data_" goes out of
|
* Here, "data" is automatically unlocked when "data_" goes out of
|
||||||
* scope.
|
* scope.
|
||||||
*/
|
*/
|
||||||
template<class T, class M = std::mutex>
|
template<class T, class M, class WL, class RL>
|
||||||
class Sync
|
class SyncBase
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
M mutex;
|
M mutex;
|
||||||
|
@ -33,23 +34,22 @@ private:
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
Sync() { }
|
SyncBase() { }
|
||||||
Sync(const T & data) : data(data) { }
|
SyncBase(const T & data) : data(data) { }
|
||||||
Sync(T && data) noexcept : data(std::move(data)) { }
|
SyncBase(T && data) noexcept : data(std::move(data)) { }
|
||||||
|
|
||||||
|
template<class L>
|
||||||
class Lock
|
class Lock
|
||||||
{
|
{
|
||||||
private:
|
protected:
|
||||||
Sync * s;
|
SyncBase * s;
|
||||||
std::unique_lock<M> lk;
|
L lk;
|
||||||
friend Sync;
|
friend SyncBase;
|
||||||
Lock(Sync * s) : s(s), lk(s->mutex) { }
|
Lock(SyncBase * s) : s(s), lk(s->mutex) { }
|
||||||
public:
|
public:
|
||||||
Lock(Lock && l) : s(l.s) { abort(); }
|
Lock(Lock && l) : s(l.s) { abort(); }
|
||||||
Lock(const Lock & l) = delete;
|
Lock(const Lock & l) = delete;
|
||||||
~Lock() { }
|
~Lock() { }
|
||||||
T * operator -> () { return &s->data; }
|
|
||||||
T & operator * () { return s->data; }
|
|
||||||
|
|
||||||
void wait(std::condition_variable & cv)
|
void wait(std::condition_variable & cv)
|
||||||
{
|
{
|
||||||
|
@ -83,7 +83,34 @@ public:
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
Lock lock() { return Lock(this); }
|
struct WriteLock : Lock<WL>
|
||||||
|
{
|
||||||
|
T * operator -> () { return &WriteLock::s->data; }
|
||||||
|
T & operator * () { return WriteLock::s->data; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Acquire write (exclusive) access to the inner value.
|
||||||
|
*/
|
||||||
|
WriteLock lock() { return WriteLock(this); }
|
||||||
|
|
||||||
|
struct ReadLock : Lock<RL>
|
||||||
|
{
|
||||||
|
const T * operator -> () { return &ReadLock::s->data; }
|
||||||
|
const T & operator * () { return ReadLock::s->data; }
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Acquire read access to the inner value. When using
|
||||||
|
* `std::shared_mutex`, this will use a shared lock.
|
||||||
|
*/
|
||||||
|
ReadLock read() const { return ReadLock(const_cast<SyncBase *>(this)); }
|
||||||
|
};
|
||||||
|
|
||||||
|
template<class T>
|
||||||
|
using Sync = SyncBase<T, std::mutex, std::unique_lock<std::mutex>, std::unique_lock<std::mutex>>;
|
||||||
|
|
||||||
|
template<class T>
|
||||||
|
using SharedSync = SyncBase<T, std::shared_mutex, std::unique_lock<std::shared_mutex>, std::shared_lock<std::shared_mutex>>;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue