2
0

Observer.h 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158
  1. #ifndef ANKI_UTIL_OBSERVER_H
  2. #define ANKI_UTIL_OBSERVER_H
  3. #include "anki/util/Vector.h"
  4. #include "anki/util/Functions.h"
  5. namespace anki {
  6. /// @addtogroup util
  7. /// @{
  8. /// @addtogroup patterns
  9. /// @{
  10. /// The observer interface template
  11. template<typename T>
  12. struct Observer
  13. {
  14. typedef T Value; ///< The type of the notification value
  15. virtual ~Observer()
  16. {}
  17. virtual void notify(Value notificationVal) = 0;
  18. };
  19. /// An over-qualified observer
  20. template<typename ObservingClass, typename Value,
  21. void (ObservingClass::*method)(Value)>
  22. struct SuperObserver: Observer<Value>
  23. {
  24. ObservingClass* receiver;
  25. SuperObserver(ObservingClass* receiver_)
  26. : receiver(receiver_)
  27. {
  28. ANKI_ASSERT(receiver != nullptr);
  29. }
  30. void notify(Value x)
  31. {
  32. (receiver->*method)(x);
  33. }
  34. };
  35. /// Basically a container of observers
  36. template<typename T, typename Alloc = Allocator<Observer<T>*>>
  37. class Observable
  38. {
  39. public:
  40. typedef T Value;
  41. typedef Observer<Value> ObserverType;
  42. typedef Vector<ObserverType*, Alloc> Container;
  43. Observable(const Alloc& alloc = Alloc())
  44. : observers(alloc)
  45. {}
  46. ~Observable()
  47. {
  48. Alloc alloc = observers.get_allocator();
  49. for(ObserverType* x : observers)
  50. {
  51. alloc.destroy(x);
  52. alloc.deallocate(x, 1);
  53. }
  54. }
  55. /// XXX
  56. template<typename Observer, typename... Args>
  57. Observer* newObserver(Args&&... args)
  58. {
  59. typedef typename Alloc::template rebind<Observer>::other UberAlloc;
  60. UberAlloc alloc(observers.get_allocator());
  61. Observer* ptr = alloc.allocate(1);
  62. alloc.construct(ptr, std::forward<Args>(args)...);
  63. return ptr;
  64. }
  65. /// Add a new observer. The Observable takes ownership of the
  66. /// pointer and its responsible of cleaning
  67. void addNewObserver(ObserverType* x)
  68. {
  69. observers.push_back(x);
  70. }
  71. /// Notify all observers
  72. void notifyAll(Value x)
  73. {
  74. for(ObserverType* obs : observers)
  75. {
  76. obs->notify(x);
  77. }
  78. }
  79. /// Alias to notifyAll
  80. void operator()(Value x)
  81. {
  82. notifyAll(x);
  83. }
  84. private:
  85. Container observers;
  86. };
  87. /// If a class has slots it should include this
  88. /// @code
  89. /// class Foo {
  90. /// ANKI_HAS_SLOTS(Foo)
  91. /// };
  92. /// @endcode
  93. #define ANKI_HAS_SLOTS(_class) \
  94. typedef _class ObservingType;
  95. /// Define a slot. This should follow the method declaration
  96. /// @code
  97. /// class Foo {
  98. /// ANKI_HAS_SLOTS(Foo)
  99. ///
  100. /// void slot(const float&)
  101. /// {...}
  102. /// ANKI_SLOT(updateZFar, const float&)
  103. /// };
  104. /// @endcode
  105. #define ANKI_SLOT(_slot, _type) \
  106. typedef SuperObserver<ObservingType, _type, &ObservingType::_slot> \
  107. Observing_##_slot;
  108. /// Define a signal
  109. #define ANKI_SIGNAL(_type, _name) \
  110. Observable<_type> _name;
  111. /// Define a signal with allocator
  112. #define ANKI_SIGNAL_ALLOCATOR(_Type, _name, _AllocType) \
  113. Observable<_Type, _AllocType> _name;
  114. /// It doesn't do anything. Its purpose is to make the code more understandable
  115. #define ANKI_EMIT this->
  116. /// Connect a signal to a slot
  117. /// @note Use RemovePointer so you can be able to use the macro outside of the
  118. /// _receiver body
  119. #define ANKI_CONNECT(_sender, _signal, _receiver, _slot) \
  120. do { \
  121. auto observer = (_sender)->_signal.newObserver< \
  122. RemovePointer<decltype(_receiver)>::Type::Observing_##_slot>( \
  123. _receiver); \
  124. (_sender)->_signal.addNewObserver(observer); \
  125. } while(false);
  126. /// @}
  127. /// @}
  128. } // end namespace anki
  129. #endif