weak_dynamic.hpp 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322
  1. // Boost.Geometry Index
  2. //
  3. // R-tree nodes based on static conversion, storing dynamic-size containers
  4. //
  5. // Copyright (c) 2011-2018 Adam Wulkiewicz, Lodz, Poland.
  6. //
  7. // Use, modification and distribution is subject to the Boost Software License,
  8. // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
  9. // http://www.boost.org/LICENSE_1_0.txt)
  10. #ifndef BOOST_GEOMETRY_INDEX_DETAIL_RTREE_NODE_WEAK_DYNAMIC_HPP
  11. #define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_NODE_WEAK_DYNAMIC_HPP
  12. namespace boost { namespace geometry { namespace index {
  13. namespace detail { namespace rtree {
  14. template <typename Value, typename Parameters, typename Box, typename Allocators, typename Tag>
  15. struct weak_internal_node
  16. : public weak_node<Value, Parameters, Box, Allocators, Tag>
  17. {
  18. typedef rtree::ptr_pair<Box, typename Allocators::node_pointer> element_type;
  19. typedef typename boost::container::allocator_traits
  20. <
  21. typename Allocators::internal_node_allocator_type
  22. >::template rebind_alloc<element_type> allocator_type;
  23. typedef boost::container::vector<element_type, allocator_type> elements_type;
  24. template <typename Al>
  25. inline weak_internal_node(Al const& al)
  26. : elements(allocator_type(al))
  27. {}
  28. elements_type elements;
  29. };
  30. template <typename Value, typename Parameters, typename Box, typename Allocators, typename Tag>
  31. struct weak_leaf
  32. : public weak_node<Value, Parameters, Box, Allocators, Tag>
  33. {
  34. typedef typename boost::container::allocator_traits
  35. <
  36. typename Allocators::leaf_allocator_type
  37. >::template rebind_alloc<Value> allocator_type;
  38. typedef boost::container::vector<Value, allocator_type> elements_type;
  39. template <typename Al>
  40. inline weak_leaf(Al const& al)
  41. : elements(allocator_type(al))
  42. {}
  43. elements_type elements;
  44. };
  45. // nodes traits
  46. template <typename Value, typename Parameters, typename Box, typename Allocators>
  47. struct node<Value, Parameters, Box, Allocators, node_weak_dynamic_tag>
  48. {
  49. typedef weak_node<Value, Parameters, Box, Allocators, node_weak_dynamic_tag> type;
  50. };
  51. template <typename Value, typename Parameters, typename Box, typename Allocators>
  52. struct internal_node<Value, Parameters, Box, Allocators, node_weak_dynamic_tag>
  53. {
  54. typedef weak_internal_node<Value, Parameters, Box, Allocators, node_weak_dynamic_tag> type;
  55. };
  56. template <typename Value, typename Parameters, typename Box, typename Allocators>
  57. struct leaf<Value, Parameters, Box, Allocators, node_weak_dynamic_tag>
  58. {
  59. typedef weak_leaf<Value, Parameters, Box, Allocators, node_weak_dynamic_tag> type;
  60. };
  61. // visitor traits
  62. template <typename Value, typename Parameters, typename Box, typename Allocators, bool IsVisitableConst>
  63. struct visitor<Value, Parameters, Box, Allocators, node_weak_dynamic_tag, IsVisitableConst>
  64. {
  65. typedef weak_visitor<Value, Parameters, Box, Allocators, node_weak_dynamic_tag, IsVisitableConst> type;
  66. };
  67. // allocators
  68. template <typename Allocator, typename Value, typename Parameters, typename Box, typename Tag>
  69. struct internal_node_alloc
  70. {
  71. typedef typename internal_nod
  72. <
  73. Value, Parameters, Box,
  74. allocators<Allocator, Value, Parameters, Box, Tag>,
  75. Tag
  76. >::type node_type;
  77. typedef typename boost::container::allocator_traits
  78. <
  79. Allocator
  80. >::template rebind_alloc<node_type> type;
  81. };
  82. template <typename Allocator, typename Value, typename Parameters, typename Box, typename Tag>
  83. struct leaf_alloc
  84. {
  85. typedef typename leaf
  86. <
  87. Value, Parameters, Box,
  88. allocators<Allocator, Value, Parameters, Box, Tag>,
  89. Tag
  90. >::type node_type;
  91. typedef typename ::boost::container::allocator_traits
  92. <
  93. Allocator
  94. >::template rebind_alloc<node_type> type;
  95. };
  96. template <typename Allocator, typename Value, typename Parameters, typename Box>
  97. class allocators<Allocator, Value, Parameters, Box, node_weak_dynamic_tag>
  98. : public internal_node_alloc<Allocator, Value, Parameters, Box, node_weak_dynamic_tag>::type
  99. , public leaf_alloc<Allocator, Value, Parameters, Box, node_weak_dynamic_tag>::type
  100. {
  101. typedef detail::rtree::internal_node_alloc
  102. <
  103. Allocator, Value, Parameters, Box, node_weak_dynamic_tag
  104. > internal_node_alloc;
  105. typedef detail::rtree::leaf_alloc
  106. <
  107. Allocator, Value, Parameters, Box, node_weak_dynamic_tag
  108. > leaf_alloc;
  109. typedef detail::rtree::node_alloc
  110. <
  111. Allocator, Value, Parameters, Box, node_weak_dynamic_tag
  112. > node_alloc;
  113. public:
  114. typedef typename internal_node_alloc::type internal_node_allocator_type;
  115. typedef typename leaf_alloc::type leaf_allocator_type;
  116. typedef typename node_alloc::traits::pointer node_pointer;
  117. private:
  118. typedef typename boost::container::allocator_traits
  119. <
  120. leaf_allocator_type // leaf_allocator_type for consistency with weak_leaf
  121. >::template rebind_alloc<Value> value_allocator_type;
  122. typedef boost::container::allocator_traits<value_allocator_type> value_allocator_traits;
  123. public:
  124. typedef Allocator allocator_type;
  125. typedef Value value_type;
  126. typedef typename value_allocator_traits::reference reference;
  127. typedef typename value_allocator_traits::const_reference const_reference;
  128. typedef typename value_allocator_traits::size_type size_type;
  129. typedef typename value_allocator_traits::difference_type difference_type;
  130. typedef typename value_allocator_traits::pointer pointer;
  131. typedef typename value_allocator_traits::const_pointer const_pointer;
  132. inline allocators()
  133. : internal_node_allocator_type()
  134. , leaf_allocator_type()
  135. {}
  136. template <typename Alloc>
  137. inline explicit allocators(Alloc const& alloc)
  138. : internal_node_allocator_type(alloc)
  139. , leaf_allocator_type(alloc)
  140. {}
  141. inline allocators(BOOST_FWD_REF(allocators) a)
  142. : internal_node_allocator_type(boost::move(a.internal_node_allocator()))
  143. , leaf_allocator_type(boost::move(a.leaf_allocator()))
  144. {}
  145. inline allocators & operator=(BOOST_FWD_REF(allocators) a)
  146. {
  147. internal_node_allocator() = ::boost::move(a.internal_node_allocator());
  148. leaf_allocator() = ::boost::move(a.leaf_allocator());
  149. return *this;
  150. }
  151. #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
  152. inline allocators & operator=(allocators const& a)
  153. {
  154. internal_node_allocator() = a.internal_node_allocator();
  155. leaf_allocator() = a.leaf_allocator();
  156. return *this;
  157. }
  158. #endif
  159. void swap(allocators & a)
  160. {
  161. boost::swap(internal_node_allocator(), a.internal_node_allocator());
  162. boost::swap(leaf_allocator(), a.leaf_allocator());
  163. }
  164. bool operator==(allocators const& a) const { return leaf_allocator() == a.leaf_allocator(); }
  165. template <typename Alloc>
  166. bool operator==(Alloc const& a) const { return leaf_allocator() == leaf_allocator_type(a); }
  167. Allocator allocator() const { return Allocator(leaf_allocator()); }
  168. internal_node_allocator_type & internal_node_allocator() { return *this; }
  169. internal_node_allocator_type const& internal_node_allocator() const { return *this; }
  170. leaf_allocator_type & leaf_allocator() { return *this; }
  171. leaf_allocator_type const& leaf_allocator() const { return *this; }
  172. };
  173. // create_node_impl
  174. template <typename BaseNodePtr, typename Node>
  175. struct create_weak_node
  176. {
  177. template <typename AllocNode>
  178. static inline BaseNodePtr apply(AllocNode & alloc_node)
  179. {
  180. typedef boost::container::allocator_traits<AllocNode> Al;
  181. typedef typename Al::pointer P;
  182. P p = Al::allocate(alloc_node, 1);
  183. if ( 0 == p )
  184. throw_runtime_error("boost::geometry::index::rtree node creation failed");
  185. scoped_deallocator<AllocNode> deallocator(p, alloc_node);
  186. Al::construct(alloc_node, boost::to_address(p), alloc_node);
  187. deallocator.release();
  188. return p;
  189. }
  190. };
  191. // destroy_node_impl
  192. template <typename Node>
  193. struct destroy_weak_node
  194. {
  195. template <typename AllocNode, typename BaseNodePtr>
  196. static inline void apply(AllocNode & alloc_node, BaseNodePtr n)
  197. {
  198. typedef boost::container::allocator_traits<AllocNode> Al;
  199. typedef typename Al::pointer P;
  200. P p(&static_cast<Node&>(rtree::get<Node>(*n)));
  201. Al::destroy(alloc_node, boost::addressof(*p));
  202. Al::deallocate(alloc_node, p, 1);
  203. }
  204. };
  205. // create_node
  206. template <typename Allocators, typename Value, typename Parameters, typename Box, typename Tag>
  207. struct create_node<
  208. Allocators,
  209. weak_internal_node<Value, Parameters, Box, Allocators, Tag>
  210. >
  211. {
  212. static inline typename Allocators::node_pointer
  213. apply(Allocators & allocators)
  214. {
  215. return create_weak_node<
  216. typename Allocators::node_pointer,
  217. weak_internal_node<Value, Parameters, Box, Allocators, Tag>
  218. >::apply(allocators.internal_node_allocator());
  219. }
  220. };
  221. template <typename Allocators, typename Value, typename Parameters, typename Box, typename Tag>
  222. struct create_node<
  223. Allocators,
  224. weak_leaf<Value, Parameters, Box, Allocators, Tag>
  225. >
  226. {
  227. static inline typename Allocators::node_pointer
  228. apply(Allocators & allocators)
  229. {
  230. return create_weak_node<
  231. typename Allocators::node_pointer,
  232. weak_leaf<Value, Parameters, Box, Allocators, Tag>
  233. >::apply(allocators.leaf_allocator());
  234. }
  235. };
  236. // destroy_node
  237. template <typename Allocators, typename Value, typename Parameters, typename Box, typename Tag>
  238. struct destroy_node<
  239. Allocators,
  240. weak_internal_node<Value, Parameters, Box, Allocators, Tag>
  241. >
  242. {
  243. static inline void apply(Allocators & allocators, typename Allocators::node_pointer n)
  244. {
  245. destroy_weak_node<
  246. weak_internal_node<Value, Parameters, Box, Allocators, Tag>
  247. >::apply(allocators.internal_node_allocator(), n);
  248. }
  249. };
  250. template <typename Allocators, typename Value, typename Parameters, typename Box, typename Tag>
  251. struct destroy_node<
  252. Allocators,
  253. weak_leaf<Value, Parameters, Box, Allocators, Tag>
  254. >
  255. {
  256. static inline void apply(Allocators & allocators, typename Allocators::node_pointer n)
  257. {
  258. destroy_weak_node<
  259. weak_leaf<Value, Parameters, Box, Allocators, Tag>
  260. >::apply(allocators.leaf_allocator(), n);
  261. }
  262. };
  263. }} // namespace detail::rtree
  264. }}} // namespace boost::geometry::index
  265. #endif // BOOST_GEOMETRY_INDEX_DETAIL_RTREE_NODE_WEAK_DYNAMIC_HPP