CsPointer  2.0.0
cs_nodemanager.h
1 
19 #ifndef LIB_CS_NODEMANAGER_H
20 #define LIB_CS_NODEMANAGER_H
21 
22 #include <cs_intrusive_pointer.h>
23 
24 #include <algorithm>
25 #include <vector>
26 
27 namespace CsPointer {
28 
29 enum class VisitChildren {
30  Recursive,
31  NonRecursive,
32 };
33 
34 enum class VisitStatus {
35  VisitMore,
36  Finished,
37 };
38 
39 template <typename T, typename Policy = CsIntrusiveDefaultPolicy>
41 {
42  public:
43  using size_type = typename std::vector<CsIntrusivePointer<T, Policy>>::size_type;
44 
45  CsNodeManager() = default;
46 
47  virtual ~CsNodeManager()
48  {
49  // ensure the objects in m_children are destoryed before
50  // m_children goes out of scope
51 
52  clear();
53  }
54 
55  CsNodeManager(const CsNodeManager &other) = default;
56  CsNodeManager &operator=(const CsNodeManager &other) = default;
57 
58  CsNodeManager(CsNodeManager &&other) = default;
59  CsNodeManager &operator=(CsNodeManager && other) = default;
60 
61  void add_child(T *child) {
62  m_children.push_back(CsIntrusivePointer<T, Policy>(child));
63  }
64 
66  m_children.push_back(std::move(child));
67  }
68 
69  const std::vector<CsIntrusivePointer<T, Policy>> &children() const {
70  return m_children;
71  }
72 
73  void clear() {
74  // swap used to prevent a race condition
75 
76  std::vector<CsIntrusivePointer<T, Policy>> tmp;
77  swap(m_children, tmp);
78  }
79 
80  template <typename U>
82 
83  template <typename U, typename F>
84  CsIntrusivePointer<U, Policy> find_child(const F &lambda) const;
85 
86  template <typename U>
87  std::vector<CsIntrusivePointer<U, Policy>> find_children() const;
88 
89  template <typename U, typename F>
90  std::vector<CsIntrusivePointer<U, Policy>> find_children(const F &lambda) const;
91 
92  void move_child(size_type source, size_type dest) {
93 
94  if (source == dest) {
95  // do nothing
96 
97  } else if (source < dest) {
98  std::rotate(m_children.begin() + source, m_children.begin() + source + 1,
99  m_children.begin() + dest + 1);
100 
101  } else {
102  std::rotate(m_children.rend() - source - 1, m_children.rend() - source,
103  m_children.rend() - dest);
104  }
105 
106  }
107 
108  bool remove_child(T *child) {
109  auto iter = std::find(m_children.begin(), m_children.end(), child);
110 
111  if (iter != m_children.end()) {
112  m_children.erase(iter);
113  return true;
114  }
115 
116  return false;
117  }
118 
120  T *ptr = child.get();
121  return remove_child(ptr);
122  }
123 
124  template <typename U = T, typename F>
125  VisitStatus visit(const F &lambda, VisitChildren option = VisitChildren::Recursive) const;
126 
127  private:
128  std::vector<CsIntrusivePointer<T, Policy>> m_children;
129 };
130 
131 template <typename T, typename Policy>
132 template <typename U>
134 {
135  CsIntrusivePointer<U, Policy> retval = nullptr;
136 
137  auto lambda_internal = [&retval] (auto item) {
138  retval = item;
139  return VisitStatus::Finished;
140  };
141 
142  visit<U>(lambda_internal);
143 
144  return retval;
145 }
146 
147 template <typename T, typename Policy>
148 template <typename U, typename F>
150 {
151  CsIntrusivePointer<U, Policy> retval = nullptr;
152 
153  auto lambda_internal = [&retval, &lambda] (auto item) {
154  if (lambda(item) == true) {
155  retval = item;
156  return VisitStatus::Finished;
157  }
158 
159  return VisitStatus::VisitMore;
160  };
161 
162  visit<U>(lambda_internal);
163 
164  return retval;
165 }
166 
167 template <typename T, typename Policy>
168 template <typename U>
169 std::vector<CsIntrusivePointer<U, Policy>> CsNodeManager<T, Policy>::find_children() const
170 {
171  std::vector<CsIntrusivePointer<U, Policy>> retval;
172 
173  auto lambda_internal = [&retval] (auto item) {
174  retval.push_back(item);
175  return VisitStatus::VisitMore;
176  };
177 
178  visit<U>(lambda_internal);
179 
180  return retval;
181 }
182 
183 template <typename T, typename Policy>
184 template <typename U, typename F>
185 std::vector<CsIntrusivePointer<U, Policy>> CsNodeManager<T, Policy>::find_children(const F &lambda) const
186 {
187  std::vector<CsIntrusivePointer<U, Policy>> retval;
188 
189  auto lambda_internal = [&retval, &lambda] (auto item) {
190  if (lambda(item) == true) {
191  retval.push_back(item);
192  }
193 
194  return VisitStatus::VisitMore;
195  };
196 
197  visit<U>(lambda_internal);
198 
199  return retval;
200 }
201 
202 template <typename T, typename Policy>
203 template <typename U, typename F>
204 VisitStatus CsNodeManager<T, Policy>::visit(const F &lambda, VisitChildren option) const
205 {
206  enum VisitStatus retval = VisitStatus::VisitMore;
207 
208  for (const auto &item : m_children) {
209 
210  if constexpr(std::is_same_v<T, U>) {
211  retval = lambda(item);
212 
213  if (retval == VisitStatus::Finished) {
214  return retval;
215  }
216 
217  } else {
218  const CsIntrusivePointer<U, Policy> &child = dynamic_pointer_cast<U>(item);
219 
220  if (child != nullptr) {
221  retval = lambda(child);
222 
223  if (retval == VisitStatus::Finished) {
224  return retval;
225  }
226  }
227  }
228 
229  if (option == VisitChildren::Recursive) {
230  retval = item->template visit<U>(lambda);
231 
232  if (retval == VisitStatus::Finished) {
233  return retval;
234  }
235  }
236  }
237 
238  return retval;
239 }
240 
241 } // end namespace
242 
243 #endif
VisitStatus visit(const F &lambda, VisitChildren option=VisitChildren::Recursive) const
Definition: cs_nodemanager.h:204
Pointer get() const noexcept
Definition: cs_intrusive_pointer.h:280
bool remove_child(const CsIntrusivePointer< T, Policy > &child)
Definition: cs_nodemanager.h:119
bool remove_child(T *child)
Definition: cs_nodemanager.h:108
CsIntrusivePointer< U, Policy > find_child() const
Definition: cs_nodemanager.h:133
const std::vector< CsIntrusivePointer< T, Policy > > & children() const
Definition: cs_nodemanager.h:69
Manages a pointer to an object, the reference count is stored in the object.
Definition: cs_intrusive_pointer.h:130
CsNodeManager & operator=(const CsNodeManager &other) = default
void clear()
Definition: cs_nodemanager.h:73
void add_child(T *child)
Definition: cs_nodemanager.h:61
virtual ~CsNodeManager()
Definition: cs_nodemanager.h:47
void move_child(size_type source, size_type dest)
Definition: cs_nodemanager.h:92
typename std::vector< CsIntrusivePointer< T, Policy > >::size_type size_type
Definition: cs_nodemanager.h:43
Manages a container of intrusive pointers.
Definition: cs_nodemanager.h:40
std::vector< CsIntrusivePointer< U, Policy > > find_children() const
Definition: cs_nodemanager.h:169
void add_child(CsIntrusivePointer< T, Policy > child)
Definition: cs_nodemanager.h:65
Namespace for the CsPointer library.