test_throwing_node.hpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322
  1. // Boost.Geometry Index
  2. //
  3. // R-tree nodes storing static-size containers
  4. // test version throwing exceptions on creation
  5. //
  6. // Copyright (c) 2011-2014 Adam Wulkiewicz, Lodz, Poland.
  7. //
  8. // Use, modification and distribution is subject to the Boost Software License,
  9. // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
  10. // http://www.boost.org/LICENSE_1_0.txt)
  11. #ifndef BOOST_GEOMETRY_INDEX_TEST_RTREE_THROWING_NODE_HPP
  12. #define BOOST_GEOMETRY_INDEX_TEST_RTREE_THROWING_NODE_HPP
  13. #include <rtree/exceptions/test_throwing.hpp>
  14. struct throwing_nodes_stats
  15. {
  16. static void reset_counters() { get_internal_nodes_counter_ref() = 0; get_leafs_counter_ref() = 0; }
  17. static size_t internal_nodes_count() { return get_internal_nodes_counter_ref(); }
  18. static size_t leafs_count() { return get_leafs_counter_ref(); }
  19. static size_t & get_internal_nodes_counter_ref() { static size_t cc = 0; return cc; }
  20. static size_t & get_leafs_counter_ref() { static size_t cc = 0; return cc; }
  21. };
  22. namespace boost { namespace geometry { namespace index {
  23. template <size_t MaxElements, size_t MinElements>
  24. struct linear_throwing : public linear<MaxElements, MinElements> {};
  25. template <size_t MaxElements, size_t MinElements>
  26. struct quadratic_throwing : public quadratic<MaxElements, MinElements> {};
  27. template <size_t MaxElements, size_t MinElements, size_t OverlapCostThreshold = 0, size_t ReinsertedElements = detail::default_rstar_reinserted_elements_s<MaxElements>::value>
  28. struct rstar_throwing : public rstar<MaxElements, MinElements, OverlapCostThreshold, ReinsertedElements> {};
  29. namespace detail { namespace rtree {
  30. // options implementation (from options.hpp)
  31. struct node_throwing_static_tag {};
  32. template <size_t MaxElements, size_t MinElements>
  33. struct options_type< linear_throwing<MaxElements, MinElements> >
  34. {
  35. typedef options<
  36. linear_throwing<MaxElements, MinElements>,
  37. insert_default_tag, choose_by_content_diff_tag, split_default_tag, linear_tag,
  38. node_throwing_static_tag
  39. > type;
  40. };
  41. template <size_t MaxElements, size_t MinElements>
  42. struct options_type< quadratic_throwing<MaxElements, MinElements> >
  43. {
  44. typedef options<
  45. quadratic_throwing<MaxElements, MinElements>,
  46. insert_default_tag, choose_by_content_diff_tag, split_default_tag, quadratic_tag,
  47. node_throwing_static_tag
  48. > type;
  49. };
  50. template <size_t MaxElements, size_t MinElements, size_t OverlapCostThreshold, size_t ReinsertedElements>
  51. struct options_type< rstar_throwing<MaxElements, MinElements, OverlapCostThreshold, ReinsertedElements> >
  52. {
  53. typedef options<
  54. rstar_throwing<MaxElements, MinElements, OverlapCostThreshold, ReinsertedElements>,
  55. insert_reinsert_tag, choose_by_overlap_diff_tag, split_default_tag, rstar_tag,
  56. node_throwing_static_tag
  57. > type;
  58. };
  59. }} // namespace detail::rtree
  60. // node implementation
  61. namespace detail { namespace rtree {
  62. template <typename Value, typename Parameters, typename Box, typename Allocators>
  63. struct variant_internal_node<Value, Parameters, Box, Allocators, node_throwing_static_tag>
  64. {
  65. typedef throwing_varray<
  66. rtree::ptr_pair<Box, typename Allocators::node_pointer>,
  67. Parameters::max_elements + 1
  68. > elements_type;
  69. template <typename Alloc>
  70. inline variant_internal_node(Alloc const&) { throwing_nodes_stats::get_internal_nodes_counter_ref()++; }
  71. inline ~variant_internal_node() { throwing_nodes_stats::get_internal_nodes_counter_ref()--; }
  72. // required because variants are initialized using node object
  73. // temporary must be taken into account
  74. inline variant_internal_node(variant_internal_node const& n)
  75. : elements(n.elements)
  76. {
  77. throwing_nodes_stats::get_internal_nodes_counter_ref()++;
  78. }
  79. #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
  80. inline variant_internal_node(variant_internal_node && n)
  81. : elements(boost::move(n.elements))
  82. {
  83. throwing_nodes_stats::get_internal_nodes_counter_ref()++;
  84. }
  85. #endif
  86. elements_type elements;
  87. private:
  88. variant_internal_node & operator=(variant_internal_node const& n);
  89. };
  90. template <typename Value, typename Parameters, typename Box, typename Allocators>
  91. struct variant_leaf<Value, Parameters, Box, Allocators, node_throwing_static_tag>
  92. {
  93. typedef throwing_varray<Value, Parameters::max_elements + 1> elements_type;
  94. template <typename Alloc>
  95. inline variant_leaf(Alloc const&) { throwing_nodes_stats::get_leafs_counter_ref()++; }
  96. inline ~variant_leaf() { throwing_nodes_stats::get_leafs_counter_ref()--; }
  97. // required because variants are initialized using node object
  98. // temporary must be taken into account
  99. inline variant_leaf(variant_leaf const& n)
  100. : elements(n.elements)
  101. {
  102. throwing_nodes_stats::get_leafs_counter_ref()++;
  103. }
  104. #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
  105. inline variant_leaf(variant_leaf && n)
  106. : elements(boost::move(n.elements))
  107. {
  108. throwing_nodes_stats::get_leafs_counter_ref()++;
  109. }
  110. #endif
  111. elements_type elements;
  112. private:
  113. variant_leaf & operator=(variant_leaf const& n);
  114. };
  115. // nodes traits
  116. template <typename Value, typename Parameters, typename Box, typename Allocators>
  117. struct node<Value, Parameters, Box, Allocators, node_throwing_static_tag>
  118. {
  119. typedef boost::variant<
  120. variant_leaf<Value, Parameters, Box, Allocators, node_throwing_static_tag>,
  121. variant_internal_node<Value, Parameters, Box, Allocators, node_throwing_static_tag>
  122. > type;
  123. };
  124. template <typename Value, typename Parameters, typename Box, typename Allocators>
  125. struct internal_node<Value, Parameters, Box, Allocators, node_throwing_static_tag>
  126. {
  127. typedef variant_internal_node<Value, Parameters, Box, Allocators, node_throwing_static_tag> type;
  128. };
  129. template <typename Value, typename Parameters, typename Box, typename Allocators>
  130. struct leaf<Value, Parameters, Box, Allocators, node_throwing_static_tag>
  131. {
  132. typedef variant_leaf<Value, Parameters, Box, Allocators, node_throwing_static_tag> type;
  133. };
  134. // visitor traits
  135. template <typename Value, typename Parameters, typename Box, typename Allocators, bool IsVisitableConst>
  136. struct visitor<Value, Parameters, Box, Allocators, node_throwing_static_tag, IsVisitableConst>
  137. {
  138. typedef static_visitor<> type;
  139. };
  140. // allocators
  141. template <typename Allocator, typename Value, typename Parameters, typename Box>
  142. class allocators<Allocator, Value, Parameters, Box, node_throwing_static_tag>
  143. : public Allocator::template rebind<
  144. typename node<
  145. Value, Parameters, Box,
  146. allocators<Allocator, Value, Parameters, Box, node_throwing_static_tag>,
  147. node_throwing_static_tag
  148. >::type
  149. >::other
  150. {
  151. typedef typename Allocator::template rebind<
  152. Value
  153. >::other value_allocator_type;
  154. public:
  155. typedef Allocator allocator_type;
  156. typedef Value value_type;
  157. typedef value_type & reference;
  158. typedef const value_type & const_reference;
  159. typedef typename value_allocator_type::size_type size_type;
  160. typedef typename value_allocator_type::difference_type difference_type;
  161. typedef typename value_allocator_type::pointer pointer;
  162. typedef typename value_allocator_type::const_pointer const_pointer;
  163. typedef typename Allocator::template rebind<
  164. typename node<Value, Parameters, Box, allocators, node_throwing_static_tag>::type
  165. >::other::pointer node_pointer;
  166. // typedef typename Allocator::template rebind<
  167. // typename internal_node<Value, Parameters, Box, allocators, node_throwing_static_tag>::type
  168. // >::other::pointer internal_node_pointer;
  169. typedef typename Allocator::template rebind<
  170. typename node<Value, Parameters, Box, allocators, node_throwing_static_tag>::type
  171. >::other node_allocator_type;
  172. inline allocators()
  173. : node_allocator_type()
  174. {}
  175. template <typename Alloc>
  176. inline explicit allocators(Alloc const& alloc)
  177. : node_allocator_type(alloc)
  178. {}
  179. inline allocators(BOOST_FWD_REF(allocators) a)
  180. : node_allocator_type(boost::move(a.node_allocator()))
  181. {}
  182. inline allocators & operator=(BOOST_FWD_REF(allocators) a)
  183. {
  184. node_allocator() = boost::move(a.node_allocator());
  185. return *this;
  186. }
  187. #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
  188. inline allocators & operator=(allocators const& a)
  189. {
  190. node_allocator() = a.node_allocator();
  191. return *this;
  192. }
  193. #endif
  194. void swap(allocators & a)
  195. {
  196. boost::swap(node_allocator(), a.node_allocator());
  197. }
  198. bool operator==(allocators const& a) const { return node_allocator() == a.node_allocator(); }
  199. template <typename Alloc>
  200. bool operator==(Alloc const& a) const { return node_allocator() == node_allocator_type(a); }
  201. Allocator allocator() const { return Allocator(node_allocator()); }
  202. node_allocator_type & node_allocator() { return *this; }
  203. node_allocator_type const& node_allocator() const { return *this; }
  204. };
  205. struct node_bad_alloc : public std::exception
  206. {
  207. const char * what() const throw() { return "internal node creation failed."; }
  208. };
  209. struct throwing_node_settings
  210. {
  211. static void throw_if_required()
  212. {
  213. // throw if counter meets max count
  214. if ( get_max_calls_ref() <= get_calls_counter_ref() )
  215. throw node_bad_alloc();
  216. else
  217. ++get_calls_counter_ref();
  218. }
  219. static void reset_calls_counter() { get_calls_counter_ref() = 0; }
  220. static void set_max_calls(size_t mc) { get_max_calls_ref() = mc; }
  221. static size_t & get_calls_counter_ref() { static size_t cc = 0; return cc; }
  222. static size_t & get_max_calls_ref() { static size_t mc = (std::numeric_limits<size_t>::max)(); return mc; }
  223. };
  224. // create_node
  225. template <typename Allocators, typename Value, typename Parameters, typename Box>
  226. struct create_node<
  227. Allocators,
  228. variant_internal_node<Value, Parameters, Box, Allocators, node_throwing_static_tag>
  229. >
  230. {
  231. static inline typename Allocators::node_pointer
  232. apply(Allocators & allocators)
  233. {
  234. // throw if counter meets max count
  235. throwing_node_settings::throw_if_required();
  236. return create_variant_node<
  237. typename Allocators::node_pointer,
  238. variant_internal_node<Value, Parameters, Box, Allocators, node_throwing_static_tag>
  239. >::apply(allocators.node_allocator());
  240. }
  241. };
  242. template <typename Allocators, typename Value, typename Parameters, typename Box>
  243. struct create_node<
  244. Allocators,
  245. variant_leaf<Value, Parameters, Box, Allocators, node_throwing_static_tag>
  246. >
  247. {
  248. static inline typename Allocators::node_pointer
  249. apply(Allocators & allocators)
  250. {
  251. // throw if counter meets max count
  252. throwing_node_settings::throw_if_required();
  253. return create_variant_node<
  254. typename Allocators::node_pointer,
  255. variant_leaf<Value, Parameters, Box, Allocators, node_throwing_static_tag>
  256. >::apply(allocators.node_allocator());
  257. }
  258. };
  259. }} // namespace detail::rtree
  260. }}} // namespace boost::geometry::index
  261. #endif // BOOST_GEOMETRY_INDEX_TEST_RTREE_THROWING_NODE_HPP