diff options
| author | Roman Smrž <roman.smrz@seznam.cz> | 2021-02-17 22:15:27 +0100 | 
|---|---|---|
| committer | Roman Smrž <roman.smrz@seznam.cz> | 2021-02-19 19:40:58 +0100 | 
| commit | 5dc467310ddebeae8dcb6262f5499f37382711ab (patch) | |
| tree | 77dc6c6fd0abec84246aaacfbf5a8d471081e2ae /include | |
| parent | d42ed33bb9112d80ae9adc926b7bd818a4d35f8d (diff) | |
WatchedHead object allowing to stop watching Head
Diffstat (limited to 'include')
| -rw-r--r-- | include/erebos/storage.h | 43 | 
1 files changed, 39 insertions, 4 deletions
| 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 <future>  #include <memory>  #include <optional> +#include <stdexcept>  #include <string>  #include <variant>  #include <vector> @@ -99,6 +100,7 @@ public:  protected:  	template<typename T> friend class Head; +	template<typename T> friend class WatchedHead;  	Storage(const std::shared_ptr<const Priv> 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<Ref> updateHead(UUID type, UUID id, const Ref & old, const std::function<Ref(const Ref &)> &); -	void watchHead(UUID type, UUID id, const std::function<void(const Ref &)>) const; +	int watchHead(UUID type, UUID id, const std::function<void(const Ref &)>) const; +	void unwatchHead(UUID type, UUID id, int watchId) const;  };  class Digest @@ -472,6 +475,8 @@ void filterAncestors(std::vector<Stored<T>> & xs)  	}  } +template<class T> class WatchedHead; +  template<class T>  class Head  { @@ -489,13 +494,34 @@ public:  	const Ref & ref() const { return mstored.ref(); }  	std::optional<Head<T>> update(const std::function<Stored<T>(const Stored<T> &)> &) const; -	void watch(const std::function<void(const Head<T> &)> &) const; +	WatchedHead<T> watch(const std::function<void(const Head<T> &)> &) const;  private:  	UUID mid;  	Stored<T> mstored;  }; +template<class T> +class WatchedHead : public Head<T> +{ +	friend class Head<T>; +	WatchedHead(const Head<T> & h, int watcherId): +		Head<T>(h), watcherId(watcherId) {} +	WatchedHead(WatchedHead<T> && h): +		Head<T>(h), watcherId(h.watcherId) +	{ h.watcherId = -1; } +	int watcherId; + +public: +	WatchedHead<T> & operator=(const Head<T> & h) { +		if (Head<T>::id() != h.id()) +			throw std::runtime_error("WatchedHead ID mismatch"); +		static_cast<Head<T> &>(*this) = h; +		return *this; +	} +	~WatchedHead(); +}; +  template<typename T>  std::optional<Head<T>> Storage::head(UUID id) const  { @@ -545,11 +571,20 @@ std::optional<Head<T>> Head<T>::update(const std::function<Stored<T>(const Store  }  template<typename T> -void Head<T>::watch(const std::function<void(const Head<T> &)> & watcher) const +WatchedHead<T> Head<T>::watch(const std::function<void(const Head<T> &)> & 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<T>(id, ref));  	}); +	return WatchedHead<T>(*this, wid); +} + +template<class T> +WatchedHead<T>::~WatchedHead() +{ +	if (watcherId >= 0) +		Head<T>::stored().ref().storage().unwatchHead( +				T::headTypeId, Head<T>::id(), watcherId);  }  } |