diff options
author | Eelco Dolstra <eelco.dolstra@logicblox.com> | 2016-02-25 11:25:11 +0100 |
---|---|---|
committer | Eelco Dolstra <eelco.dolstra@logicblox.com> | 2016-02-25 11:25:11 +0100 |
commit | f1bdeac9864de8cd9994bb41da79f3a4d812dadc (patch) | |
tree | 9ea00480f826dc8d8d8248e11323266a42f9d4ae /src/libutil/sync.hh | |
parent | 9b05d5848c2fce73b75b3411e362c2bd48d53dcb (diff) | |
parent | 152b1d6bf9c89b4db9848475e3000821e159d479 (diff) |
Merge branch 'master' into new-cli
Diffstat (limited to 'src/libutil/sync.hh')
-rw-r--r-- | src/libutil/sync.hh | 78 |
1 files changed, 78 insertions, 0 deletions
diff --git a/src/libutil/sync.hh b/src/libutil/sync.hh new file mode 100644 index 000000000..c99c098ac --- /dev/null +++ b/src/libutil/sync.hh @@ -0,0 +1,78 @@ +#pragma once + +#include <mutex> +#include <condition_variable> +#include <cassert> + +namespace nix { + +/* This template class ensures synchronized access to a value of type + T. It is used as follows: + + struct Data { int x; ... }; + + Sync<Data> data; + + { + auto data_(data.lock()); + data_->x = 123; + } + + Here, "data" is automatically unlocked when "data_" goes out of + scope. +*/ + +template<class T> +class Sync +{ +private: + std::mutex mutex; + T data; + +public: + + Sync() { } + Sync(const T & data) : data(data) { } + + class Lock + { + private: + Sync * s; + std::unique_lock<std::mutex> lk; + friend Sync; + Lock(Sync * s) : s(s), lk(s->mutex) { } + public: + Lock(Lock && l) : s(l.s) { abort(); } + Lock(const Lock & l) = delete; + ~Lock() { } + T * operator -> () { return &s->data; } + T & operator * () { return s->data; } + + void wait(std::condition_variable & cv) + { + assert(s); + cv.wait(lk); + } + + template<class Rep, class Period, class Predicate> + bool wait_for(std::condition_variable & cv, + const std::chrono::duration<Rep, Period> & duration, + Predicate pred) + { + assert(s); + return cv.wait_for(lk, duration, pred); + } + + template<class Clock, class Duration> + std::cv_status wait_until(std::condition_variable & cv, + const std::chrono::time_point<Clock, Duration> & duration) + { + assert(s); + return cv.wait_until(lk, duration); + } + }; + + Lock lock() { return Lock(this); } +}; + +} |