summaryrefslogtreecommitdiff
path: root/include/erebos/state.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/erebos/state.h')
-rw-r--r--include/erebos/state.h107
1 files changed, 107 insertions, 0 deletions
diff --git a/include/erebos/state.h b/include/erebos/state.h
new file mode 100644
index 0000000..16be464
--- /dev/null
+++ b/include/erebos/state.h
@@ -0,0 +1,107 @@
+#pragma once
+
+#include <erebos/storage.h>
+#include <erebos/uuid.h>
+
+#include <memory>
+#include <optional>
+#include <vector>
+
+namespace erebos {
+
+using std::optional;
+using std::shared_ptr;
+using std::vector;
+
+template<typename T>
+struct SharedType
+{
+ static const UUID id;
+ static T(*const load)(const vector<Ref> &);
+ static vector<Ref>(*const store)(const T &);
+};
+
+#define DECLARE_SHARED_TYPE(T) \
+ template<> const UUID erebos::SharedType<T>::id; \
+ template<> T(*const erebos::SharedType<T>::load)(const std::vector<erebos::Ref> &); \
+ template<> std::vector<erebos::Ref>(*const erebos::SharedType<T>::store) (const T &);
+
+#define DEFINE_SHARED_TYPE(T, id_, load_, store_) \
+ template<> const UUID erebos::SharedType<T>::id { id_ }; \
+ template<> T(*const erebos::SharedType<T>::load)(const vector<Ref> &) { load_ }; \
+ template<> std::vector<erebos::Ref>(*const erebos::SharedType<T>::store) (const T &) { store_ };
+
+class Identity;
+
+class LocalState
+{
+public:
+ LocalState();
+ explicit LocalState(const Ref &);
+ static LocalState load(const Ref & ref) { return LocalState(ref); }
+ Ref store(const Storage &) const;
+
+ static const UUID headTypeId;
+
+ const optional<Identity> & identity() const;
+ LocalState identity(const Identity &) const;
+
+ template<class T> T shared() const;
+ template<class T> LocalState shared(const T & x) const;
+
+ vector<Ref> sharedRefs() const;
+ LocalState sharedRefAdd(const Ref &) const;
+
+ template<typename T> static T lens(const LocalState &);
+
+private:
+ vector<Ref> lookupShared(UUID) const;
+ LocalState updateShared(UUID, const vector<Ref> &) const;
+
+ struct Priv;
+ std::shared_ptr<Priv> p;
+};
+
+class SharedState
+{
+public:
+ template<class T> T get() const;
+ template<typename T> static T lens(const SharedState &);
+
+ bool operator==(const SharedState &) const;
+ bool operator!=(const SharedState &) const;
+
+private:
+ vector<Ref> lookup(UUID) const;
+
+ struct Priv;
+ SharedState(shared_ptr<Priv> && p): p(std::move(p)) {}
+ shared_ptr<Priv> p;
+ friend class LocalState;
+};
+
+template<class T>
+T LocalState::shared() const
+{
+ return SharedType<T>::load(lookupShared(SharedType<T>::id));
+}
+
+template<class T>
+LocalState LocalState::shared(const T & x) const
+{
+ return updateShared(SharedType<T>::id, SharedType<T>::store(x));
+}
+
+template<class T>
+T SharedState::get() const
+{
+ return SharedType<T>::load(lookup(SharedType<T>::id));
+}
+
+template<class T>
+T SharedState::lens(const SharedState & x)
+{
+ return x.get<T>();
+}
+
+}