Observer.h 3.3 KB

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