aboutsummaryrefslogtreecommitdiff
path: root/src/libutil/sync.hh
diff options
context:
space:
mode:
authorEelco Dolstra <eelco.dolstra@logicblox.com>2016-02-23 15:00:59 +0100
committerEelco Dolstra <eelco.dolstra@logicblox.com>2016-02-23 15:00:59 +0100
commite292144d46e3fbb24ee9ee67f1682b268373921b (patch)
tree318c8baaca0739076dcbcbe0d530f5e8d97fc204 /src/libutil/sync.hh
parentc0b7a8a0b576d5fcbcb25c412836dc885b7eb0fe (diff)
RemoteStore: Make thread-safe
This allows a RemoteStore object to be used safely from multiple threads concurrently. It will make multiple daemon connections if necessary. Note: pool.hh and sync.hh have been copied from the Hydra source tree.
Diffstat (limited to 'src/libutil/sync.hh')
-rw-r--r--src/libutil/sync.hh78
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..3abffa7c7
--- /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;
+ friend Sync;
+ Lock(Sync * s) : s(s) { s->mutex.lock(); }
+ public:
+ Lock(Lock && l) : s(l.s) { l.s = 0; }
+ Lock(const Lock & l) = delete;
+ ~Lock() { if (s) s->mutex.unlock(); }
+ T * operator -> () { return &s->data; }
+ T & operator * () { return s->data; }
+
+ /* FIXME: performance impact of condition_variable_any? */
+ void wait(std::condition_variable_any & cv)
+ {
+ assert(s);
+ cv.wait(s->mutex);
+ }
+
+ template<class Rep, class Period, class Predicate>
+ bool wait_for(std::condition_variable_any & cv,
+ const std::chrono::duration<Rep, Period> & duration,
+ Predicate pred)
+ {
+ assert(s);
+ return cv.wait_for(s->mutex, duration, pred);
+ }
+
+ template<class Clock, class Duration>
+ std::cv_status wait_until(std::condition_variable_any & cv,
+ const std::chrono::time_point<Clock, Duration> & duration)
+ {
+ assert(s);
+ return cv.wait_until(s->mutex, duration);
+ }
+ };
+
+ Lock lock() { return Lock(this); }
+};
+
+}