From 6232d13f5321b87ddf12a1aa36b4545da45f173d Mon Sep 17 00:00:00 2001 From: Joel Klinghed Date: Wed, 17 Nov 2021 22:34:57 +0100 Subject: Travel3: Simple image and video display site Reads the images and videos from filesystem and builds a site in memroy. --- src/observer_list.hh | 148 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 148 insertions(+) create mode 100644 src/observer_list.hh (limited to 'src/observer_list.hh') diff --git a/src/observer_list.hh b/src/observer_list.hh new file mode 100644 index 0000000..86cdc03 --- /dev/null +++ b/src/observer_list.hh @@ -0,0 +1,148 @@ +#ifndef OBSERVER_LIST_HH +#define OBSERVER_LIST_HH + +#include "common.hh" + +#include +#include + +template +class ObserverList { +public: + class iterator { + public: + iterator() + : list_(nullptr), index_(0), end_(0) {} + + ~iterator() { + if (list_) + list_->release(); + } + + iterator(iterator const& it) + : list_(it.list_), index_(it.index_), end_(it.end_) { + if (list_) { + list_->aquire(); + while (index_ < end_ && !list_->observers_[index_]) + ++index_; + } + } + + iterator& operator=(iterator const& it) { + if (list_ != it.list_) { + if (list_) + list_->release(); + list_ = it.list_; + if (list_) + list_->aquire(); + } + index_ = it.index_; + end_ = it.end_; + return *this; + } + + explicit operator bool() { + return index_ < end_; + } + + T& operator*() { + return *list_->observers_[index_]; + } + + T* operator->() { + return list_->observers_[index_]; + } + + iterator operator++(int) { + iterator ret(*this); + ++(*this); + return ret; + } + + iterator& operator++() { + if (index_ < end_) { + do { + ++index_; + } while (index_ < end_ && !list_->observers_[index_]); + } + return *this; + } + + private: + friend class ObserverList; + + iterator(ObserverList* list, size_t index, size_t end) + : list_(list), index_(index), end_(end) { + list_->aquire(); + while (index_ < end_ && !list_->observers_[index_]) + ++index_; + } + + ObserverList* list_; + size_t index_; + size_t end_; + }; + + ObserverList() = default; + ~ObserverList() { + assert(active_ == 0); + } + + bool empty() const { + return observers_.empty(); + } + + void add(T* observer) { + assert(std::find(observers_.begin(), observers_.end(), observer) + == observers_.end()); + observers_.push_back(observer); + } + + void remove(T* observer) { + auto it = std::find(observers_.begin(), observers_.end(), observer); + if (it != observers_.end()) { + if (active_) { + *it = nullptr; + ++deleted_; + } else { + observers_.erase(it); + } + } else { + assert(false); + } + } + + iterator notify() { + return iterator(this, 0, observers_.size()); + } + +private: + void aquire() { + ++active_; + } + + void release() { + assert(active_ > 0); + --active_; + if (active_ == 0 && deleted_) + cleanup(); + } + + void cleanup() { + size_t i = observers_.size(); + while (deleted_ && i > 0) { + --i; + if (!observers_[i]) { + --deleted_; + observers_.erase(observers_.begin() + i); + } + } + assert(deleted_ == 0); + } + + std::vector observers_; + unsigned active_{0}; + unsigned deleted_{0}; +}; + +#endif // OBSERVER_LIST_HH -- cgit v1.2.3-70-g09d2