From 5dc467310ddebeae8dcb6262f5499f37382711ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Roman=20Smr=C5=BE?= Date: Wed, 17 Feb 2021 22:15:27 +0100 Subject: WatchedHead object allowing to stop watching Head --- include/erebos/storage.h | 43 +++++++++++++++++++++++++++++++++++++++---- 1 file changed, 39 insertions(+), 4 deletions(-) (limited to 'include/erebos') diff --git a/include/erebos/storage.h b/include/erebos/storage.h index 07e7a4f..10ced57 100644 --- a/include/erebos/storage.h +++ b/include/erebos/storage.h @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -99,6 +100,7 @@ public: protected: template friend class Head; + template friend class WatchedHead; Storage(const std::shared_ptr p): PartialStorage(p) {} @@ -107,7 +109,8 @@ protected: static UUID storeHead(UUID type, const Ref & ref); static bool replaceHead(UUID type, UUID id, const Ref & old, const Ref & ref); static std::optional updateHead(UUID type, UUID id, const Ref & old, const std::function &); - void watchHead(UUID type, UUID id, const std::function) const; + int watchHead(UUID type, UUID id, const std::function) const; + void unwatchHead(UUID type, UUID id, int watchId) const; }; class Digest @@ -472,6 +475,8 @@ void filterAncestors(std::vector> & xs) } } +template class WatchedHead; + template class Head { @@ -489,13 +494,34 @@ public: const Ref & ref() const { return mstored.ref(); } std::optional> update(const std::function(const Stored &)> &) const; - void watch(const std::function &)> &) const; + WatchedHead watch(const std::function &)> &) const; private: UUID mid; Stored mstored; }; +template +class WatchedHead : public Head +{ + friend class Head; + WatchedHead(const Head & h, int watcherId): + Head(h), watcherId(watcherId) {} + WatchedHead(WatchedHead && h): + Head(h), watcherId(h.watcherId) + { h.watcherId = -1; } + int watcherId; + +public: + WatchedHead & operator=(const Head & h) { + if (Head::id() != h.id()) + throw std::runtime_error("WatchedHead ID mismatch"); + static_cast &>(*this) = h; + return *this; + } + ~WatchedHead(); +}; + template std::optional> Storage::head(UUID id) const { @@ -545,11 +571,20 @@ std::optional> Head::update(const std::function(const Store } template -void Head::watch(const std::function &)> & watcher) const +WatchedHead Head::watch(const std::function &)> & watcher) const { - stored().ref().storage().watchHead(T::headTypeId, id(), [id = id(), watcher] (const Ref & ref) { + int wid = stored().ref().storage().watchHead(T::headTypeId, id(), [id = id(), watcher] (const Ref & ref) { watcher(Head(id, ref)); }); + return WatchedHead(*this, wid); +} + +template +WatchedHead::~WatchedHead() +{ + if (watcherId >= 0) + Head::stored().ref().storage().unwatchHead( + T::headTypeId, Head::id(), watcherId); } } -- cgit v1.2.3