summaryrefslogtreecommitdiff
path: root/src/observers.hh
diff options
context:
space:
mode:
authorJoel Klinghed <the_jk@yahoo.com>2017-09-26 21:58:23 +0200
committerJoel Klinghed <the_jk@yahoo.com>2017-09-26 21:58:23 +0200
commit811e04305457108bc32d8895fd9bd274715d02fc (patch)
tree4bf4e89448ce3be4858404a7ea81c166ab2b8d37 /src/observers.hh
parent37e7c66d65e00b9543003aba1f0f9b13a8dc151b (diff)
Use a modification safe observers list
Diffstat (limited to 'src/observers.hh')
-rw-r--r--src/observers.hh71
1 files changed, 71 insertions, 0 deletions
diff --git a/src/observers.hh b/src/observers.hh
new file mode 100644
index 0000000..3e56e6b
--- /dev/null
+++ b/src/observers.hh
@@ -0,0 +1,71 @@
+#ifndef OBSERVERS_HH
+#define OBSERVERS_HH
+
+#include <memory>
+#include <vector>
+
+template<typename T>
+class Observers {
+public:
+ Observers()
+ : current_(0), protected_(0), removed_(0) {
+ }
+
+ void add(T* observer) {
+ if (!observer) return;
+ for (auto it = observers_.begin(); it != observers_.end(); ++it) {
+ if (*it == observer) return;
+ }
+ observers_.push_back(observer);
+ }
+
+ void remove(T* observer) {
+ if (!observer) return;
+ size_t index = 0;
+ for (; index < observers_.size(); ++index) {
+ if (observers_[index] == observer) {
+ if (index < protected_) {
+ observers_[index] = nullptr;
+ ++removed_;
+ } else {
+ observers_.erase(observers_.begin() + index);
+ }
+ break;
+ }
+ }
+ }
+
+ T* first() {
+ if (protected_) return nullptr;
+ if (observers_.empty()) return nullptr;
+ protected_ = observers_.size();
+ return observers_[current_];
+ }
+
+ T* next() {
+ if (current_ >= protected_) return nullptr;
+ ++current_;
+ if (current_ >= protected_) {
+ if (removed_) {
+ for (size_t i = protected_; i > 0; --i) {
+ if (!observers_[i - 1]) {
+ observers_.erase(observers_.begin() + i - 1);
+ if (--removed_ == 0) break;
+ }
+ }
+ }
+ protected_ = current_ = 0;
+ return nullptr;
+ }
+ auto ret = observers_[current_];
+ return ret ? ret : next();
+ }
+
+private:
+ size_t current_;
+ size_t protected_;
+ size_t removed_;
+ std::vector<T*> observers_;
+};
+
+#endif // OBSERVERS_HH