OpenLexocad  27.1
Observer.h
Go to the documentation of this file.
1 #ifndef __OBSERVER_H__
2 #define __OBSERVER_H__
3 
4 
5 #include <Base/Timer.h>
6 #include <Base/Log.h>
7 
8 
9 #include <list>
10 #include <set>
11 #include <vector>
12 
13 namespace Base
14 {
15 template <class _MessageType>
16 class Subject;
17 
25 template <class _MessageType>
26 class Observer
27 {
28 public:
34  : _observerPriority(1) // default priority
35  {
36 
37  };
38 
43  virtual ~Observer()
44  {
45  cDebug("~Observer %s %x", this->name() ? this->name() : "No Name", this);
46  if (!_subjects.empty())
47  {
48  auto copy_subjects = _subjects;
49  cWarn("Observer %s %x is not detached!!!!", this->name() ? this->name() : "No Name", this);
50  for (auto s : copy_subjects)
51  s->detach(this);
52  }
53  __deadVal = 0xDEADBEEF;
54  };
55 
56 
57 
63  virtual void onChange(Subject<_MessageType>* rCaller, _MessageType rcReason) = 0;
64 
70  virtual void onDestroy(Subject<_MessageType>& /*rCaller*/) {}
71 
77  virtual const char* name(void) { return "<no name>"; }
78 
82  void setObserverPriority(int priority) { _observerPriority = priority; }
83  inline int getObserverPriority() const { return _observerPriority; }
84 
85  void setAttached(Subject<_MessageType>* t) { _subjects.push_back(t); };
87  {
88  _subjects.erase( std::find( _subjects.begin(), _subjects.end(), t ));
89  //_subjects.erase(std::remove(_subjects.begin(), _subjects.end(), t),_subjects.end());
90  };
91 
92  long __deadVal = 0xBADEAFFE;
93 private:
94 
95  std::vector<Subject<_MessageType>*> _subjects;
96  int _observerPriority;
97 };
98 
99 
107 template <class _MessageType>
108 class Subject
109 {
110 public:
112  typedef _MessageType MessageType;
114 
116  {
117  ObserverHolder() = default;
118  ObserverHolder(ObserverType* aobserverPtr) :observerPtr(aobserverPtr),observerPriority(aobserverPtr->getObserverPriority()), isAttached(true), isDeleted(false) { }
121  mutable bool isAttached;
122  mutable bool isDeleted;
123  };
124 
125 
126 
131  Subject() : _running_notify{false} { };
132 
137  virtual ~Subject()
138  {
139 
140  if( _running_notify )
141  {
142  cWarn("FATAL ERROR, ~Subject %X call while running notify!" );
143  cDebuggerBreak("FATAL ERROR ~Subject call running notify!");
144  }
145 
146  if( _ObserverSet.size() != 0 )
147  {
148  cWarn("Not detached all observers yet" );
149  }
150  }
151 
159  {
160 
161  ToObserv->setAttached(this);
162 
163  std::string name = ToObserv->name() ? ToObserv->name() : "No Name";
164  std::ostringstream oss;
165  oss << " " << ToObserv;
166  name += oss.str();
167 
168  if( _running_notify )
169  {
170  cDebug("Subject %x, attach Observer %s %X while running notify",this, ToObserv->name() ? ToObserv->name() : "No Name", ToObserv);
171  if( ToObserv->__deadVal == 0xDEADBEEF )
172  cWarn("UGGS!");
173  _ObserverSet_AddedLater.insert(ObserverHolder(ToObserv));
174  }
175  else
176  {
177  if( _ObserverSet.find(ToObserv) == _ObserverSet.end() )
178  {
179  cDebug("Subject %x, attach Observer %s %X ",this, ToObserv->name() ? ToObserv->name() : "No Name", ToObserv);
180  _ObserverSet.insert(ObserverHolder(ToObserv));
181  }
182  else
183  {
184  cWarn("Subject %x, attach Observer %s %X already attached",this, ToObserv->name() ? ToObserv->name() : "No Name", ToObserv);
185  _ObserverSet.insert(ObserverHolder(ToObserv));
186  }
187  }
188 
189 
190  }
191 
199  {
200  cDebug("DETACH 0x%X",ToObserv);
201  if( _running_notify )
202  {
203  ObserverSetType::iterator it = _ObserverSet.find(ObserverHolder(ToObserv));
204  if( it != _ObserverSet.end() )
205  {
206  cWarn("**** Subject %x, detach Observer %s %X while running notify",this, ToObserv->name() ? ToObserv->name() : "No Name", ToObserv);
207  (*it).isAttached = false;
208  }
209 
210  auto it2 = _ObserverSet_AddedLater.find(ObserverHolder(ToObserv));
211  if( it2 != _ObserverSet_AddedLater.end() )
212  {
213  cWarn("**** Subject %x, detach Observer %s %X while running notify",this, ToObserv->name() ? ToObserv->name() : "No Name", ToObserv);
214  (*it2).isAttached = false;
215  }
216 
217  }
218  else
219  {
220  if (_ObserverSet.find(ToObserv) != _ObserverSet.end())
221  {
222  cDebug("Subject %x, detach Observer %s %X",this, ToObserv->name() ? ToObserv->name() : "No Name", ToObserv);
223  ToObserv->setDetached(this);
224  _ObserverSet.erase(ToObserv);
225  }
226  else
227  {
228  cWarn("Subject %x, detach Observer %s %X not found",this, ToObserv->name() ? ToObserv->name() : "No Name", ToObserv);
229  }
230  }
231 
232  }
233 
235  {
236  ObserverSetType::iterator it = _ObserverSet.find(ObserverHolder(ToObserv));
237  if( it != _ObserverSet.end() )
238  {
239  cWarn("**** Subject %x, detach Observer %s %X while running notify",this, ToObserv->name() ? ToObserv->name() : "No Name", ToObserv);
240  (*it).isDeleted = true;
241  }
242  auto it2 = _ObserverSet_AddedLater.find(ObserverHolder(ToObserv));
243  if( it2 != _ObserverSet_AddedLater.end() )
244  {
245  cWarn("**** Subject %x, detach Observer %s %X while running notify",this, ToObserv->name() ? ToObserv->name() : "No Name", ToObserv);
246  (*it2).isDeleted = true;
247  }
248 
249  }
250 
254  void detachAll()
255  {
256  auto observerSetCopy = _ObserverSet;
257  for (auto observer : observerSetCopy)
258  {
259  if( observer.isAttached )
260  observer.observerPtr->setDetached(this);
261  }
262 
263  auto observerSet_AddedLater_Copy = _ObserverSet_AddedLater;
264  for (auto observer : observerSet_AddedLater_Copy)
265  {
266  if( observer.isAttached )
267  observer.observerPtr->setDetached(this);
268  }
269 
270  _ObserverSet.clear();
271  _ObserverSet_AddedLater.clear();
272  }
273 
281  void notify_internal(_MessageType& rcReason, size_t deep)
282  {
283  if( deep > 10 )
284  {
285  cWarn("ERROR notify_internal, to deep recursion!");
286  cDebuggerBreak("ERROR notify_internal, to deep recursion!");
287  return;
288  }
289 
291  {
292  // Was detached, maybe in another observer.
293  if( !observer.isAttached )
294  continue;
295 
297  {
298  // store name here, maybe it is possible, that observer will be deleted in onChange method, so we do not want to access Iter->first after that
299  std::string observerName = (observer.observerPtr)->name() ? (observer.observerPtr)->name() : "<no Name>";
300 
301  Base::Timer t;
302  (observer.observerPtr)->onChange(this, rcReason); // send OnChange-signal
303  auto myt = t.elapsedMS();
304 
305  if (_observerTime.find(observerName) == _observerTime.end())
306  _observerTime[observerName] = myt;
307  else
308  _observerTime[observerName] += myt;
309 
310  if (myt > 50)
311  cWarn(" Observer (%s) need %f ms", observerName.c_str(), t.elapsedMS());
312  else if (myt > 5)
313  cDebug(" Observer (%s) need %f ms", observerName.c_str(), t.elapsedMS());
314  }
315  else
316  {
317  if( observer.observerPtr->__deadVal == 0xBADEAFFE )
318  (observer.observerPtr)->onChange(this, rcReason); // send OnChange-signal
319  else
320  cWarn("Urgg deleted observer");
321  }
322 
323  }
324 
325 
326  // Is a Observer attached while notify?
327  int counter = 10;
328  while( !_ObserverSet_AddedLater.empty() )
329  {
330  auto copy_ObserverSet_AddedLater = getObserverSortedByPriority(_ObserverSet_AddedLater);
331  _ObserverSet_AddedLater.clear();
332  for (auto observer : copy_ObserverSet_AddedLater)
333  {
334  if( observer.isAttached )
335  observer.observerPtr->onChange(this, rcReason); // send OnChange-signal
336  _ObserverSet.insert(observer);
337  }
338 
339  if( (counter--) <= 0 )
340  {
341  cWarn("ERROR _ObserverSet_AddedLater, to many repeats!");
342  cDebuggerBreak("ERROR notify_internal, to deep recursion!");
343  break;
344  }
345  }
346 
347  // Now process the messages we got while running notify...
348  auto copy_messages_WhileRunningNotify = _messages_WhileRunningNotify;
350  for(auto &message : copy_messages_WhileRunningNotify )
351  {
352  notify_internal( message, deep+1 );
353  }
354 
355  }
356 
357  void notify(_MessageType& rcReason)
358  {
359  if (_running_notify)
360  {
361  _messages_WhileRunningNotify.push_back(rcReason);
362  return;
363  }
364  _running_notify = true;
365  notify_internal(rcReason, 1);
366  _running_notify = false;
367 
368  auto observerSetCopy = _ObserverSet;
369  for (auto observer : observerSetCopy)
370  {
371  if( !observer.isAttached )
372  _ObserverSet.erase( observer );
373  }
374 
375  auto observerSet_AddedLater_Copy = _ObserverSet_AddedLater;
376  for (auto observer : observerSet_AddedLater_Copy)
377  {
378  if( !observer.isAttached )
380  }
381 
382  }
383 
388  Observer<_MessageType>* get(const char* Name)
389  {
390  const char* OName;
391  for (auto observer : _ObserverSet)
392  {
393 
394  OName = observer.observerPtr->name(); // get the name
395  if (OName && strcmp(OName, Name) == 0)
396  return observer.observerPtr;
397  }
398 
399  return nullptr;
400  }
401 
402  std::vector<Observer<_MessageType>*> getAll()
403  {
404  std::vector<Observer<_MessageType>*> ret;
405  for (auto observer : _ObserverSet)
406  {
407  ret.push_back(observer.observerPtr);
408  }
409  return ret;
410 
411  }
412 
413  virtual const char* subject_name(void) { return "NO SUBJECT NAME"; }
414 
415  void resetObserverTime() { _observerTime.clear(); }
416 
417  std::map<std::string, double> getObserverTime() { return _observerTime; }
418 
419 
420 
421 
422 protected:
423 
424 
425  // Compare observers according priority. Higher priority first.
427  {
428  bool operator()(const ObserverHolder& o1, const ObserverHolder& o2) const
429  {
430  return o1.observerPtr < o2.observerPtr;
431  }
432  };
433 
434 
435  typedef std::set<ObserverHolder, CompareObservers> ObserverSetType;
436 
437  std::vector<ObserverHolder> getObserverSortedByPriority( const ObserverSetType& obs )
438  {
439  std::vector<ObserverHolder> ret( obs.begin(), obs.end() ) ;
440 
441  std::sort(ret.begin(), ret.end(), [](const ObserverHolder& a,const ObserverHolder& b)
442  { return a.observerPriority > b.observerPriority; });
443 
444  return ret;
445  }
446 
449 
452  std::map<std::string, double> _observerTime;
453 };
454 
455 
456 } // namespace Base
457 
458 
459 #endif // __OBSERVER_H__
LX_BASE_EXPORT LOGLEVEL getLogLevel()
std::map< std::string, double > _observerTime
Definition: Observer.h:452
void detach(Observer< _MessageType > *ToObserv)
Definition: Observer.h:198
ObserverHolder(ObserverType *aobserverPtr)
Definition: Observer.h:118
void notify(_MessageType &rcReason)
Definition: Observer.h:357
virtual ~Subject()
Definition: Observer.h:137
Observer< _MessageType > ObserverType
Definition: Observer.h:111
LX_BASE_EXPORT Base::LogClass cDebug()
bool isDeleted
Definition: Observer.h:122
void notify_internal(_MessageType &rcReason, size_t deep)
Definition: Observer.h:281
Definition: Observer.h:26
Observer< _MessageType > * get(const char *Name)
Definition: Observer.h:388
void attach(Observer< _MessageType > *ToObserv)
Definition: Observer.h:158
Core::PropertyText name
Definition: CoreDocument.h:167
_MessageType MessageType
Definition: Observer.h:112
Definition: Log.h:18
void setAttached(Subject< _MessageType > *t)
Definition: Observer.h:85
std::set< ObserverHolder, CompareObservers > ObserverSetType
Definition: Observer.h:435
LX_BASE_EXPORT void cDebuggerBreak(char *message)
Definition: Observer.h:16
int getObserverPriority() const
Definition: Observer.h:83
long __deadVal
Definition: Observer.h:92
Definition: Observer.h:115
ObserverSetType _ObserverSet_AddedLater
Set of attached observers.
Definition: Observer.h:448
std::vector< Observer< _MessageType > * > getAll()
Definition: Observer.h:402
void observerDeleted(Observer< _MessageType > *ToObserv)
Definition: Observer.h:234
Observer()
Definition: Observer.h:33
ObserverType * observerPtr
Definition: Observer.h:119
int observerPriority
Definition: Observer.h:120
std::map< std::string, double > getObserverTime()
Definition: Observer.h:417
basic_observer< entity > observer
Alias declaration for the most common use case.
Definition: entt.hpp:3793
bool _running_notify
Set of attached observers at running notify.
Definition: Observer.h:450
Subject()
Definition: Observer.h:131
void setObserverPriority(int priority)
Definition: Observer.h:82
Subject< _MessageType > SubjectType
Definition: Observer.h:113
virtual ~Observer()
Definition: Observer.h:43
bool isAttached
Definition: Observer.h:121
Definition: Observer.h:426
Definition: AbstractXMLReader.h:5
std::list< _MessageType > _messages_WhileRunningNotify
Definition: Observer.h:451
virtual void onDestroy(Subject< _MessageType > &)
Definition: Observer.h:70
std::vector< ObserverHolder > getObserverSortedByPriority(const ObserverSetType &obs)
Definition: Observer.h:437
virtual void onChange(Subject< _MessageType > *rCaller, _MessageType rcReason)=0
void setDetached(Subject< _MessageType > *t)
Definition: Observer.h:86
virtual const char * name(void)
Definition: Observer.h:77
ObserverSetType _ObserverSet
Definition: Observer.h:447
LX_BASE_EXPORT Base::LogClass cWarn()
void resetObserverTime()
Definition: Observer.h:415
bool operator()(const ObserverHolder &o1, const ObserverHolder &o2) const
Definition: Observer.h:428
void detachAll()
Definition: Observer.h:254
virtual const char * subject_name(void)
Definition: Observer.h:413