Caffe2 - C++ API
A deep learning, cross platform ML framework
observer.h
1 #pragma once
2 
3 #include <memory>
4 #include <unordered_set>
5 
6 #include "caffe2/core/logging.h"
7 
8 namespace caffe2 {
9 
14 template <class T>
15 class ObserverBase {
16  public:
17  explicit ObserverBase(T* subject) : subject_(subject) {}
18 
19  virtual void Start() {}
20  virtual void Stop() {}
21 
22  virtual std::string debugInfo() {
23  return "Not implemented.";
24  }
25 
26  virtual ~ObserverBase() noexcept {};
27 
28  T* subject() const {
29  return subject_;
30  }
31 
32  virtual std::unique_ptr<ObserverBase<T>> rnnCopy(T* subject, int rnn_order)
33  const {
34  return nullptr;
35  };
36 
37  protected:
38  T* subject_;
39 };
40 
44 template <class T>
45 class Observable {
46  public:
47  Observable() = default;
48 
49  Observable(Observable&&) = default;
50  Observable& operator =(Observable&&) = default;
51 
52  virtual ~Observable() = default;
53 
54  C10_DISABLE_COPY_AND_ASSIGN(Observable);
55 
56  using Observer = ObserverBase<T>;
57 
58  /* Returns a reference to the observer after addition. */
59  const Observer* AttachObserver(std::unique_ptr<Observer> observer) {
60  CAFFE_ENFORCE(observer, "Couldn't attach a null observer.");
61  std::unordered_set<const Observer*> observers;
62  for (auto& ob : observers_list_) {
63  observers.insert(ob.get());
64  }
65 
66  const auto* observer_ptr = observer.get();
67  if (observers.count(observer_ptr)) {
68  return observer_ptr;
69  }
70  observers_list_.push_back(std::move(observer));
71  UpdateCache();
72 
73  return observer_ptr;
74  }
75 
80  std::unique_ptr<Observer> DetachObserver(const Observer* observer_ptr) {
81  for (auto it = observers_list_.begin(); it != observers_list_.end(); ++it) {
82  if (it->get() == observer_ptr) {
83  auto res = std::move(*it);
84  observers_list_.erase(it);
85  UpdateCache();
86  return res;
87  }
88  }
89  return nullptr;
90  }
91 
92  virtual size_t NumObservers() {
93  return num_observers_;
94  }
95 
96  private:
97  inline static void StartObserver(Observer* observer) {
98  try {
99  observer->Start();
100  } catch (const std::exception& e) {
101  LOG(ERROR) << "Exception from observer: " << e.what();
102  } catch (...) {
103  LOG(ERROR) << "Exception from observer: unknown";
104  }
105  }
106 
107  inline static void StopObserver(Observer* observer) {
108  try {
109  observer->Stop();
110  } catch (const std::exception& e) {
111  LOG(ERROR) << "Exception from observer: " << e.what();
112  } catch (...) {
113  LOG(ERROR) << "Exception from observer: unknown";
114  }
115  }
116 
117  void UpdateCache() {
118  num_observers_ = observers_list_.size();
119  if (num_observers_ != 1) {
120  // we cannot take advantage of the cache
121  return;
122  }
123  observer_cache_ = observers_list_[0].get();
124  }
125 
126  public:
127  void StartAllObservers() {
128  // do not access observers_list_ unless necessary
129  if (num_observers_ == 0) {
130  return;
131  } else if (num_observers_ == 1) {
132  StartObserver(observer_cache_);
133  } else {
134  for (auto& observer : observers_list_) {
135  StartObserver(observer.get());
136  }
137  }
138  }
139 
140  void StopAllObservers() {
141  // do not access observers_list_ unless necessary
142  if (num_observers_ == 0) {
143  return;
144  } else if (num_observers_ == 1) {
145  StopObserver(observer_cache_);
146  } else {
147  for (auto& observer : observers_list_) {
148  StopObserver(observer.get());
149  }
150  }
151  }
152 
153  private:
154  // an on-stack cache for fast iteration;
155  // ideally, inside StartAllObservers and StopAllObservers,
156  // we should never access observers_list_
157  Observer* observer_cache_;
158  size_t num_observers_ = 0;
159 
160  protected:
161  std::vector<std::unique_ptr<Observer>> observers_list_;
162 };
163 
164 } // namespace caffe2
Use this to implement a Observer using the Observer Pattern template.
Definition: observer.h:15
std::unique_ptr< Observer > DetachObserver(const Observer *observer_ptr)
Returns a unique_ptr to the removed observer.
Definition: observer.h:80
Inherit to make your class observable.
Definition: observer.h:45
A global dictionary that holds information about what Caffe2 modules have been loaded in the current ...
Definition: blob.h:13