Object.h 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207
  1. #ifndef ANKI_UTIL_OBJECT_H
  2. #define ANKI_UTIL_OBJECT_H
  3. #include "anki/util/Assert.h"
  4. #include "anki/util/Vector.h"
  5. #include "anki/util/StdTypes.h"
  6. #include "anki/util/Allocator.h"
  7. #include "anki/util/NonCopyable.h"
  8. #include <algorithm>
  9. namespace anki {
  10. /// @addtogroup util
  11. /// @{
  12. /// @addtogroup patterns
  13. /// @{
  14. /// The default set of callbacks. They do nothing
  15. template<typename T>
  16. struct ObjectCallbackCollection
  17. {
  18. /// Called when a child is been removed from a parent
  19. void onChildRemoved(T* child, T* parent)
  20. {
  21. ANKI_ASSERT(child);
  22. // Do nothing
  23. }
  24. /// Called when a child is been added to a parent
  25. void onChildAdded(T* child, T* parent)
  26. {
  27. ANKI_ASSERT(child && parent);
  28. // Do nothing
  29. }
  30. };
  31. /// A hierarchical object
  32. template<typename T, typename Alloc = Allocator<T>,
  33. typename TCallbackCollection = ObjectCallbackCollection<T>>
  34. class Object: public NonCopyable
  35. {
  36. public:
  37. typedef T Value;
  38. typedef Vector<Value*, Alloc> Container;
  39. typedef TCallbackCollection CallbackCollection;
  40. /// Calls addChild if parent is not nullptr
  41. ///
  42. /// @param parent_ The parent. Can be nullptr
  43. /// @param alloc The allocator to use on internal allocations
  44. /// @param callbacks_ A set of callbacks
  45. Object(
  46. Value* parent_,
  47. const Alloc& alloc = Alloc(),
  48. const CallbackCollection& callbacks_ = CallbackCollection())
  49. : parent(nullptr), // Set to nullptr or prepare for assertion
  50. children(alloc),
  51. callbacks(callbacks_)
  52. {
  53. if(parent_ != nullptr)
  54. {
  55. parent_->addChild(getSelf());
  56. }
  57. }
  58. /// Delete children from the last entered to the first and update parent
  59. virtual ~Object()
  60. {
  61. if(parent != nullptr)
  62. {
  63. parent->removeChild(getSelf());
  64. }
  65. // Remove all children (fast version)
  66. for(Value* child : children)
  67. {
  68. child->parent = nullptr;
  69. // Pass the parent as nullptr because at this point there is
  70. // nothing you should do with a deleteding parent
  71. callbacks.onChildRemoved(child, nullptr);
  72. }
  73. }
  74. /// @name Accessors
  75. /// @{
  76. const Value* getParent() const
  77. {
  78. return parent;
  79. }
  80. Value* getParent()
  81. {
  82. return parent;
  83. }
  84. PtrSize getChildrenSize() const
  85. {
  86. return children.size();
  87. }
  88. Value& getChild(PtrSize i)
  89. {
  90. ANKI_ASSERT(i < children.size());
  91. return *children[i];
  92. }
  93. const Value& getChild(PtrSize i) const
  94. {
  95. ANKI_ASSERT(i < children.size());
  96. return *children[i];
  97. }
  98. Alloc getAllocator() const
  99. {
  100. return children.get_allocator();
  101. }
  102. /// @}
  103. /// Add a new child
  104. void addChild(Value* child)
  105. {
  106. ANKI_ASSERT(child != nullptr && "Null arg");
  107. ANKI_ASSERT(child != getSelf() && "Cannot put itself");
  108. ANKI_ASSERT(child->parent == nullptr && "Child already has parent");
  109. ANKI_ASSERT(child->findChild(getSelf()) == child->children.end()
  110. && "Cyclic add");
  111. ANKI_ASSERT(findChild(child) == children.end() && "Already a child");
  112. child->parent = getSelf();
  113. children.push_back(child);
  114. callbacks.onChildAdded(child, getSelf());
  115. }
  116. /// Remove a child
  117. void removeChild(Value* child)
  118. {
  119. ANKI_ASSERT(child != nullptr && "Null arg");
  120. ANKI_ASSERT(child->parent == getSelf() && "Child has other parent");
  121. typename Container::iterator it = findChild(child);
  122. ANKI_ASSERT(it != children.end() && "Child not found");
  123. children.erase(it);
  124. child->parent = nullptr;
  125. callbacks.onChildRemoved(child, getSelf());
  126. }
  127. /// Visit the children and the children's children. Use it with lambda
  128. template<typename VisitorFunc>
  129. void visitChildren(VisitorFunc vis)
  130. {
  131. for(Value* c : children)
  132. {
  133. vis(*c);
  134. }
  135. }
  136. /// Visit this object and move to the children. Use it with lambda
  137. template<typename VisitorFunc>
  138. void visitThisAndChildren(VisitorFunc vis)
  139. {
  140. vis(*getSelf());
  141. visitChildren(vis);
  142. }
  143. /// Visit the whole tree. Use it with lambda
  144. template<typename VisitorFunc>
  145. void visitTree(VisitorFunc vis)
  146. {
  147. // Move to root
  148. Value* root = getSelf();
  149. while(root->parent != nullptr)
  150. {
  151. root = root->parent;
  152. }
  153. root->visitThisAndChildren(vis);
  154. }
  155. private:
  156. Value* parent; ///< May be nullptr
  157. Container children;
  158. CallbackCollection callbacks; /// A set of callbacks
  159. /// Cast the Object to the given type
  160. Value* getSelf()
  161. {
  162. return static_cast<Value*>(this);
  163. }
  164. /// Find the child
  165. typename Container::iterator findChild(Value* child)
  166. {
  167. typename Container::iterator it =
  168. std::find(children.begin(), children.end(), child);
  169. return it;
  170. }
  171. };
  172. /// @}
  173. /// @}
  174. } // end namespace anki
  175. #endif