mdds
node.hpp
1 /*************************************************************************
2  *
3  * Copyright (c) 2008-2014 Kohei Yoshida
4  *
5  * Permission is hereby granted, free of charge, to any person
6  * obtaining a copy of this software and associated documentation
7  * files (the "Software"), to deal in the Software without
8  * restriction, including without limitation the rights to use,
9  * copy, modify, merge, publish, distribute, sublicense, and/or sell
10  * copies of the Software, and to permit persons to whom the
11  * Software is furnished to do so, subject to the following
12  * conditions:
13  *
14  * The above copyright notice and this permission notice shall be
15  * included in all copies or substantial portions of the Software.
16  *
17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
19  * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
21  * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
22  * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
23  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
24  * OTHER DEALINGS IN THE SOFTWARE.
25  *
26  ************************************************************************/
27 
28 #ifndef __MDDS_NODE_HXX__
29 #define __MDDS_NODE_HXX__
30 
31 #include <iostream>
32 #include <vector>
33 #include <cassert>
34 
35 #include <boost/intrusive_ptr.hpp>
36 
37 namespace mdds { namespace __st {
38 
39 #ifdef MDDS_DEBUG_NODE_BASE
40 size_t node_instance_count = 0;
41 #endif
42 
43 struct node_base
44 {
45  node_base* parent;
46  bool is_leaf;
47 
48  node_base(bool _is_leaf) : parent(nullptr), is_leaf(_is_leaf) {}
49  node_base(const node_base& r) : parent(nullptr), is_leaf(r.is_leaf) {}
50 };
51 
52 template<typename T>
53 struct nonleaf_node : public node_base
54 {
55  typedef typename T::nonleaf_value_type nonleaf_value_type;
56  typedef typename T::fill_nonleaf_value_handler fill_nonleaf_value_handler;
57  typedef typename T::init_handler init_handler;
58  typedef typename T::dispose_handler dispose_handler;
59 #ifdef MDDS_UNIT_TEST
60  typedef typename T::to_string_handler to_string_handler;
61 #endif
62  nonleaf_value_type value_nonleaf;
63 
64  node_base* left;
66 
67 private:
68  fill_nonleaf_value_handler _hdl_fill_nonleaf;
69  init_handler _hdl_init;
70  dispose_handler _hdl_dispose;
71 #ifdef MDDS_UNIT_TEST
72  to_string_handler _hdl_to_string;
73 #endif
74 
75 public:
76  nonleaf_node() :
77  node_base(false),
78  left(nullptr),
79  right(nullptr)
80  {
81  _hdl_init(*this);
82  }
83 
89  node_base(r),
90  left(nullptr),
91  right(nullptr)
92  {
93  value_nonleaf = r.value_nonleaf;
94  }
95 
100  {
101  if (this == &r)
102  // assignment to self.
103  return *this;
104 
105  value_nonleaf = r.value_nonleaf;
106  return *this;
107  }
108 
109  ~nonleaf_node()
110  {
111  dispose();
112  }
113 
114  void dispose()
115  {
116  _hdl_dispose(*this);
117  }
118 
119  bool equals(const nonleaf_node& r) const
120  {
121  return value_nonleaf == r.value_nonleaf;
122  }
123 
124  void fill_nonleaf_value(const node_base* left_node, const node_base* right_node)
125  {
126  _hdl_fill_nonleaf(*this, left_node, right_node);
127  }
128 
129 #ifdef MDDS_UNIT_TEST
130  void dump_value() const
131  {
132  ::std::cout << _hdl_to_string(*this);
133  }
134 
135  ::std::string to_string() const
136  {
137  return _hdl_to_string(*this);
138  }
139 #endif
140 };
141 
142 template<typename T>
143 struct node : public node_base
144 {
145  typedef ::boost::intrusive_ptr<node> node_ptr;
146 
147  typedef typename T::leaf_value_type leaf_value_type;
148  typedef typename T::init_handler init_handler;
149  typedef typename T::dispose_handler dispose_handler;
150 #ifdef MDDS_UNIT_TEST
151  typedef typename T::to_string_handler to_string_handler;
152 #endif
153 
154  static size_t get_instance_count()
155  {
156 #ifdef MDDS_DEBUG_NODE_BASE
157  return node_instance_count;
158 #else
159  return 0;
160 #endif
161  }
162 
163  leaf_value_type value_leaf;
164 
165  node_ptr prev;
166  node_ptr next;
167 
168  size_t refcount;
169 private:
170  init_handler _hdl_init;
171  dispose_handler _hdl_dispose;
172 #ifdef MDDS_UNIT_TEST
173  to_string_handler _hdl_to_string;
174 #endif
175 
176 public:
177  node() : node_base(true), refcount(0)
178  {
179 #ifdef MDDS_DEBUG_NODE_BASE
180  ++node_instance_count;
181 #endif
182  _hdl_init(*this);
183  }
184 
189  node(const node& r) : node_base(r), refcount(0)
190  {
191 #ifdef MDDS_DEBUG_NODE_BASE
192  ++node_instance_count;
193 #endif
194  value_leaf = r.value_leaf;
195  }
196 
200  node& operator=(const node& r)
201  {
202  if (this == &r)
203  // assignment to self.
204  return *this;
205 
206  value_leaf = r.value_leaf;
207  return *this;
208  }
209 
210  ~node()
211  {
212 #ifdef MDDS_DEBUG_NODE_BASE
213  --node_instance_count;
214 #endif
215  dispose();
216  }
217 
218  void dispose()
219  {
220  _hdl_dispose(*this);
221  }
222 
223  bool equals(const node& r) const
224  {
225  return value_leaf == r.value_leaf;
226  }
227 
228 #ifdef MDDS_UNIT_TEST
229  void dump_value() const
230  {
231  ::std::cout << _hdl_to_string(*this);
232  }
233 
234  ::std::string to_string() const
235  {
236  return _hdl_to_string(*this);
237  }
238 #endif
239 };
240 
241 template<typename T>
242 inline void intrusive_ptr_add_ref(node<T>* p)
243 {
244  ++p->refcount;
245 }
246 
247 template<typename T>
248 inline void intrusive_ptr_release(node<T>* p)
249 {
250  --p->refcount;
251  if (!p->refcount)
252  delete p;
253 }
254 
255 template<typename T>
256 void link_nodes(typename node<T>::node_ptr& left, typename node<T>::node_ptr& right)
257 {
258  left->next = right;
259  right->prev = left;
260 }
261 
262 template<typename T>
264 {
265 public:
267  typedef typename mdds::__st::node<T>::node_ptr leaf_node_ptr;
269  typedef std::vector<nonleaf_node> nonleaf_node_pool_type;
270 
271  tree_builder(nonleaf_node_pool_type& pool) :
272  m_pool(pool), m_pool_pos(pool.begin()), m_pool_pos_end(pool.end()) {}
273 
274  nonleaf_node* build(const leaf_node_ptr& left_leaf_node)
275  {
276  if (!left_leaf_node)
277  // The left leaf node is empty. Nothing to build.
278  return nullptr;
279 
280  leaf_node_ptr node1 = left_leaf_node;
281 
282  std::vector<nonleaf_node*> node_list;
283  while (true)
284  {
285  leaf_node_ptr node2 = node1->next;
286  nonleaf_node* parent_node = make_parent_node(node1.get(), node2.get());
287  node_list.push_back(parent_node);
288 
289  if (!node2 || !node2->next)
290  // no more nodes. Break out of the loop.
291  break;
292 
293  node1 = node2->next;
294  }
295 
296  return build_tree_non_leaf(node_list);
297  }
298 
299 private:
300 
301  nonleaf_node* make_parent_node(node_base* node1, node_base* node2)
302  {
303  assert(m_pool_pos != m_pool_pos_end);
304 
305  nonleaf_node* parent_node = &(*m_pool_pos);
306  ++m_pool_pos;
307  node1->parent = parent_node;
308  parent_node->left = node1;
309  if (node2)
310  {
311  node2->parent = parent_node;
312  parent_node->right = node2;
313  }
314 
315  parent_node->fill_nonleaf_value(node1, node2);
316  return parent_node;
317  }
318 
319  nonleaf_node* build_tree_non_leaf(const std::vector<nonleaf_node*>& node_list)
320  {
321  size_t node_count = node_list.size();
322  if (node_count == 1)
323  {
324  return node_list.front();
325  }
326  else if (node_count == 0)
327  return nullptr;
328 
329  std::vector<nonleaf_node*> new_node_list;
330  nonleaf_node* node1 = nullptr;
331  typename std::vector<nonleaf_node*>::const_iterator it = node_list.begin();
332  typename std::vector<nonleaf_node*>::const_iterator it_end = node_list.end();
333  for (bool even_itr = false; it != it_end; ++it, even_itr = !even_itr)
334  {
335  if (even_itr)
336  {
337  nonleaf_node* node2 = *it;
338  nonleaf_node* parent_node = make_parent_node(node1, node2);
339  new_node_list.push_back(parent_node);
340  node1 = nullptr;
341  node2 = nullptr;
342  }
343  else
344  node1 = *it;
345  }
346 
347  if (node1)
348  {
349  // Un-paired node still needs a parent...
350  nonleaf_node* parent_node = make_parent_node(node1, nullptr);
351  new_node_list.push_back(parent_node);
352  }
353 
354  // Move up one level, and do the same procedure until the root node is reached.
355  return build_tree_non_leaf(new_node_list);
356  }
357 
358  nonleaf_node_pool_type& m_pool;
359  typename nonleaf_node_pool_type::iterator m_pool_pos;
360  typename nonleaf_node_pool_type::iterator m_pool_pos_end;
361 };
362 
363 
364 template<typename T>
365 void disconnect_all_nodes(node<T>* p)
366 {
367  if (!p)
368  return;
369 
370  p->prev.reset();
371  p->next.reset();
372  p->parent = nullptr;
373 }
374 
375 template<typename T>
376 void disconnect_leaf_nodes(node<T>* left_node, node<T>* right_node)
377 {
378  if (!left_node || !right_node)
379  return;
380 
381  // Go through all leaf nodes, and disconnect their links.
382  node<T>* cur_node = left_node;
383  do
384  {
385  node<T>* next_node = cur_node->next.get();
386  disconnect_all_nodes(cur_node);
387  cur_node = next_node;
388  }
389  while (cur_node != right_node);
390 
391  disconnect_all_nodes(right_node);
392 }
393 
394 template<typename T>
395 size_t count_leaf_nodes(const node<T>* left_end, const node<T>* right_end)
396 {
397  size_t leaf_count = 1;
398  const node<T>* p = left_end;
399  const node<T>* p_end = right_end;
400  for (; p != p_end; p = p->next.get(), ++leaf_count)
401  ;
402 
403  return leaf_count;
404 }
405 
406 inline size_t count_needed_nonleaf_nodes(size_t leaf_count)
407 {
408  size_t nonleaf_count = 0;
409  while (true)
410  {
411  if (leaf_count == 1)
412  break;
413 
414  if ((leaf_count % 2) == 1)
415  // Add one to make it an even number.
416  ++leaf_count;
417 
418  leaf_count /= 2;
419  nonleaf_count += leaf_count;
420  }
421 
422  return nonleaf_count;
423 }
424 
425 #ifdef MDDS_UNIT_TEST
426 
427 template<typename _Leaf, typename _NonLeaf>
428 class tree_dumper
429 {
430  typedef std::vector<const node_base*> node_list_type;
431 
432 public:
433  static size_t dump(const node_base* root_node)
434  {
435  if (!root_node)
436  return 0;
437 
438  node_list_type node_list;
439  node_list.push_back(root_node);
440  return dump_layer(node_list, 0);
441  }
442 
443 private:
444  static size_t dump_layer(const node_list_type& node_list, unsigned int level)
445  {
446  using ::std::cout;
447  using ::std::endl;
448 
449  if (node_list.empty())
450  return 0;
451 
452  size_t node_count = node_list.size();
453 
454  bool is_leaf = node_list.front()->is_leaf;
455  cout << "level " << level << " (" << (is_leaf?"leaf":"non-leaf") << ")" << endl;
456 
457  node_list_type new_list;
458  typename node_list_type::const_iterator it = node_list.begin(), it_end = node_list.end();
459  for (; it != it_end; ++it)
460  {
461  const node_base* p = *it;
462  if (!p)
463  {
464  cout << "(x) ";
465  continue;
466  }
467 
468  if (p->is_leaf)
469  static_cast<const _Leaf*>(p)->dump_value();
470  else
471  static_cast<const _NonLeaf*>(p)->dump_value();
472 
473  if (p->is_leaf)
474  continue;
475 
476  if (static_cast<const _NonLeaf*>(p)->left)
477  {
478  new_list.push_back(static_cast<const _NonLeaf*>(p)->left);
479  if (static_cast<const _NonLeaf*>(p)->right)
480  new_list.push_back(static_cast<const _NonLeaf*>(p)->right);
481  }
482  }
483  cout << endl;
484 
485  if (!new_list.empty())
486  node_count += dump_layer(new_list, level+1);
487 
488  return node_count;
489  }
490 };
491 
492 #endif
493 
494 }}
495 
496 #endif
Definition: node.hpp:263
node_base * right
left child nonleaf_node
Definition: node.hpp:65
bool is_leaf
parent nonleaf_node
Definition: node.hpp:46
nonleaf_node & operator=(const nonleaf_node &r)
Definition: node.hpp:99
Definition: node.hpp:43
nonleaf_node(const nonleaf_node &r)
Definition: node.hpp:88
Definition: node.hpp:53
Definition: flat_segment_tree.hpp:46
node & operator=(const node &r)
Definition: node.hpp:200
Definition: node.hpp:143
size_t refcount
next sibling leaf node.
Definition: node.hpp:168
node_ptr next
previous sibling leaf node.
Definition: node.hpp:166
node(const node &r)
Definition: node.hpp:189