varray_detail.hpp 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667
  1. // Boost.Geometry
  2. //
  3. // varray details
  4. //
  5. // Copyright (c) 2011-2013 Andrew Hundt.
  6. // Copyright (c) 2012-2023 Adam Wulkiewicz, Lodz, Poland.
  7. //
  8. // This file was modified by Oracle on 2020.
  9. // Modifications copyright (c) 2020, Oracle and/or its affiliates.
  10. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
  11. //
  12. // Use, modification and distribution is subject to the Boost Software License,
  13. // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
  14. // http://www.boost.org/LICENSE_1_0.txt)
  15. #ifndef BOOST_GEOMETRY_INDEX_DETAIL_VARRAY_DETAIL_HPP
  16. #define BOOST_GEOMETRY_INDEX_DETAIL_VARRAY_DETAIL_HPP
  17. #include <algorithm>
  18. #include <cstddef>
  19. #include <cstring>
  20. #include <limits>
  21. #include <memory>
  22. #include <type_traits>
  23. #include <boost/config.hpp>
  24. #include <boost/core/addressof.hpp>
  25. #include <boost/core/no_exceptions_support.hpp>
  26. #include <boost/iterator/iterator_traits.hpp>
  27. // TODO - move vectors iterators optimization to the other, optional file instead of checking defines?
  28. #if defined(BOOST_GEOMETRY_INDEX_DETAIL_VARRAY_ENABLE_VECTOR_OPTIMIZATION) && !defined(BOOST_NO_EXCEPTIONS)
  29. #include <vector>
  30. #include <boost/container/vector.hpp>
  31. #endif // BOOST_GEOMETRY_INDEX_DETAIL_VARRAY_ENABLE_VECTOR_OPTIMIZATION && !BOOST_NO_EXCEPTIONS
  32. namespace boost { namespace geometry { namespace index { namespace detail { namespace varray_detail
  33. {
  34. template <typename I>
  35. struct are_elements_contiguous : std::is_pointer<I>
  36. {};
  37. // EXPERIMENTAL - not finished
  38. // Conditional setup - mark vector iterators defined in known implementations
  39. // as iterators pointing to contiguous ranges
  40. #if defined(BOOST_GEOMETRY_INDEX_DETAIL_VARRAY_ENABLE_VECTOR_OPTIMIZATION) && !defined(BOOST_NO_EXCEPTIONS)
  41. template <typename Pointer>
  42. struct are_elements_contiguous<
  43. boost::container::container_detail::vector_const_iterator<Pointer>
  44. > : std::true_type
  45. {};
  46. template <typename Pointer>
  47. struct are_elements_contiguous<
  48. boost::container::container_detail::vector_iterator<Pointer>
  49. > : std::true_type
  50. {};
  51. #if defined(BOOST_DINKUMWARE_STDLIB)
  52. template <typename T>
  53. struct are_elements_contiguous<
  54. std::_Vector_const_iterator<T>
  55. > : std::true_type
  56. {};
  57. template <typename T>
  58. struct are_elements_contiguous<
  59. std::_Vector_iterator<T>
  60. > : std::true_type
  61. {};
  62. #elif defined(BOOST_GNU_STDLIB)
  63. template <typename P, typename T, typename A>
  64. struct are_elements_contiguous<
  65. __gnu_cxx::__normal_iterator<P, std::vector<T, A> >
  66. > : std::true_type
  67. {};
  68. #elif defined(_LIBCPP_VERSION)
  69. // TODO - test it first
  70. //template <typename P>
  71. //struct are_elements_contiguous<
  72. // __wrap_iter<P>
  73. //> : std::true_type
  74. //{};
  75. #else // OTHER_STDLIB
  76. // TODO - add other iterators implementations
  77. #endif // STDLIB
  78. #endif // BOOST_GEOMETRY_INDEX_DETAIL_VARRAY_ENABLE_VECTOR_OPTIMIZATION && !BOOST_NO_EXCEPTIONS
  79. template <typename I, typename O>
  80. struct is_memop_safe_for_range
  81. : std::integral_constant
  82. <
  83. bool,
  84. std::is_same
  85. <
  86. std::remove_const_t
  87. <
  88. typename ::boost::iterator_value<I>::type
  89. >,
  90. std::remove_const_t
  91. <
  92. typename ::boost::iterator_value<O>::type
  93. >
  94. >::value
  95. &&
  96. are_elements_contiguous<I>::value
  97. &&
  98. are_elements_contiguous<O>::value
  99. &&
  100. std::is_trivially_copyable
  101. <
  102. typename ::boost::iterator_value<O>::type
  103. >::value
  104. >
  105. {};
  106. template <typename I, typename V>
  107. struct is_memop_safe_for_value
  108. : std::integral_constant
  109. <
  110. bool,
  111. std::is_same
  112. <
  113. std::remove_const_t
  114. <
  115. typename ::boost::iterator_value<I>::type
  116. >,
  117. std::remove_const_t<V>
  118. >::value
  119. &&
  120. std::is_trivially_copyable
  121. <
  122. V
  123. >::value
  124. >
  125. {};
  126. // destroy(I, I)
  127. template <typename I>
  128. void destroy_dispatch(I /*first*/, I /*last*/,
  129. std::true_type /*has_trivial_destructor*/)
  130. {}
  131. template <typename I>
  132. void destroy_dispatch(I first, I last,
  133. std::false_type /*has_trivial_destructor*/)
  134. {
  135. typedef typename boost::iterator_value<I>::type value_type;
  136. for ( ; first != last ; ++first )
  137. first->~value_type();
  138. }
  139. template <typename I>
  140. void destroy(I first, I last)
  141. {
  142. typedef typename boost::iterator_value<I>::type value_type;
  143. destroy_dispatch(first, last, std::is_trivially_destructible<value_type>());
  144. }
  145. // destroy(I)
  146. template <typename I>
  147. void destroy_dispatch(I /*pos*/,
  148. std::true_type /*has_trivial_destructor*/)
  149. {}
  150. template <typename I>
  151. void destroy_dispatch(I pos,
  152. std::false_type /*has_trivial_destructor*/)
  153. {
  154. typedef typename boost::iterator_value<I>::type value_type;
  155. pos->~value_type();
  156. }
  157. template <typename I>
  158. void destroy(I pos)
  159. {
  160. typedef typename boost::iterator_value<I>::type value_type;
  161. destroy_dispatch(pos, std::is_trivially_destructible<value_type>());
  162. }
  163. // copy(I, I, O)
  164. template <typename I, typename O>
  165. inline O copy_dispatch(I first, I last, O dst,
  166. std::true_type /*use_memmove*/)
  167. {
  168. typedef typename boost::iterator_value<I>::type value_type;
  169. typename boost::iterator_difference<I>::type d = std::distance(first, last);
  170. ::memmove(boost::addressof(*dst), boost::addressof(*first), sizeof(value_type) * d);
  171. return dst + d;
  172. }
  173. template <typename I, typename O>
  174. inline O copy_dispatch(I first, I last, O dst,
  175. std::false_type /*use_memmove*/)
  176. {
  177. return std::copy(first, last, dst); // may throw
  178. }
  179. template <typename I, typename O>
  180. inline O copy(I first, I last, O dst)
  181. {
  182. return copy_dispatch(first, last, dst, is_memop_safe_for_range<I, O>()); // may throw
  183. }
  184. // uninitialized_copy(I, I, O)
  185. template <typename I, typename O>
  186. inline
  187. O uninitialized_copy_dispatch(I first, I last, O dst,
  188. std::true_type /*use_memcpy*/)
  189. {
  190. typedef typename boost::iterator_value<I>::type value_type;
  191. typename boost::iterator_difference<I>::type d = std::distance(first, last);
  192. ::memcpy(boost::addressof(*dst), boost::addressof(*first), sizeof(value_type) * d);
  193. return dst + d;
  194. }
  195. template <typename I, typename F>
  196. inline
  197. F uninitialized_copy_dispatch(I first, I last, F dst,
  198. std::false_type /*use_memcpy*/)
  199. {
  200. return std::uninitialized_copy(first, last, dst); // may throw
  201. }
  202. template <typename I, typename F>
  203. inline
  204. F uninitialized_copy(I first, I last, F dst)
  205. {
  206. return uninitialized_copy_dispatch(first, last, dst, is_memop_safe_for_range<I, F>()); // may throw
  207. }
  208. // uninitialized_move(I, I, O)
  209. template <typename I, typename O>
  210. inline
  211. O uninitialized_move_dispatch(I first, I last, O dst,
  212. std::true_type /*use_memcpy*/)
  213. {
  214. typedef typename boost::iterator_value<I>::type value_type;
  215. typename boost::iterator_difference<I>::type d = std::distance(first, last);
  216. ::memcpy(boost::addressof(*dst), boost::addressof(*first), sizeof(value_type) * d);
  217. return dst + d;
  218. }
  219. template <typename I, typename O>
  220. inline
  221. O uninitialized_move_dispatch(I first, I last, O dst,
  222. std::false_type /*use_memcpy*/)
  223. {
  224. //return boost::uninitialized_move(first, last, dst); // may throw
  225. O o = dst;
  226. BOOST_TRY
  227. {
  228. typedef typename std::iterator_traits<O>::value_type value_type;
  229. for (; first != last; ++first, ++o )
  230. new (boost::addressof(*o)) value_type(std::move(*first));
  231. }
  232. BOOST_CATCH(...)
  233. {
  234. varray_detail::destroy(dst, o);
  235. BOOST_RETHROW;
  236. }
  237. BOOST_CATCH_END
  238. return dst;
  239. }
  240. template <typename I, typename O>
  241. inline
  242. O uninitialized_move(I first, I last, O dst)
  243. {
  244. return uninitialized_move_dispatch(first, last, dst, is_memop_safe_for_range<I, O>()); // may throw
  245. }
  246. // TODO - move uses memmove - implement 2nd version using memcpy?
  247. // move(I, I, O)
  248. template <typename I, typename O>
  249. inline
  250. O move_dispatch(I first, I last, O dst,
  251. std::true_type /*use_memmove*/)
  252. {
  253. typedef typename boost::iterator_value<I>::type value_type;
  254. typename boost::iterator_difference<I>::type d = std::distance(first, last);
  255. ::memmove(boost::addressof(*dst), boost::addressof(*first), sizeof(value_type) * d);
  256. return dst + d;
  257. }
  258. template <typename I, typename O>
  259. inline
  260. O move_dispatch(I first, I last, O dst,
  261. std::false_type /*use_memmove*/)
  262. {
  263. return std::move(first, last, dst); // may throw
  264. }
  265. template <typename I, typename O>
  266. inline
  267. O move(I first, I last, O dst)
  268. {
  269. return move_dispatch(first, last, dst, is_memop_safe_for_range<I, O>()); // may throw
  270. }
  271. // move_backward(BDI, BDI, BDO)
  272. template <typename BDI, typename BDO>
  273. inline
  274. BDO move_backward_dispatch(BDI first, BDI last, BDO dst,
  275. std::true_type /*use_memmove*/)
  276. {
  277. typedef typename boost::iterator_value<BDI>::type value_type;
  278. typename boost::iterator_difference<BDI>::type d = std::distance(first, last);
  279. BDO foo(dst - d);
  280. ::memmove(boost::addressof(*foo), boost::addressof(*first), sizeof(value_type) * d);
  281. return foo;
  282. }
  283. template <typename BDI, typename BDO>
  284. inline
  285. BDO move_backward_dispatch(BDI first, BDI last, BDO dst,
  286. std::false_type /*use_memmove*/)
  287. {
  288. return std::move_backward(first, last, dst); // may throw
  289. }
  290. template <typename BDI, typename BDO>
  291. inline
  292. BDO move_backward(BDI first, BDI last, BDO dst)
  293. {
  294. return move_backward_dispatch(first, last, dst, is_memop_safe_for_range<BDI, BDO>()); // may throw
  295. }
  296. // uninitialized_move_if_noexcept(I, I, O)
  297. template <typename I, typename O>
  298. inline
  299. O uninitialized_move_if_noexcept_dispatch(I first, I last, O dst,
  300. std::true_type /*use_move*/)
  301. {
  302. return varray_detail::uninitialized_move(first, last, dst);
  303. }
  304. template <typename I, typename O>
  305. inline
  306. O uninitialized_move_if_noexcept_dispatch(I first, I last, O dst,
  307. std::false_type const& /*use_move*/)
  308. {
  309. return varray_detail::uninitialized_copy(first, last, dst);
  310. }
  311. template <typename I, typename O>
  312. inline
  313. O uninitialized_move_if_noexcept(I first, I last, O dst)
  314. {
  315. typedef std::is_nothrow_move_constructible<
  316. typename ::boost::iterator_value<O>::type
  317. > use_move;
  318. return uninitialized_move_if_noexcept_dispatch(first, last, dst, use_move()); // may throw
  319. }
  320. // move_if_noexcept(I, I, O)
  321. template <typename I, typename O>
  322. inline
  323. O move_if_noexcept_dispatch(I first, I last, O dst,
  324. std::true_type /*use_move*/)
  325. {
  326. return varray_detail::move(first, last, dst);
  327. }
  328. template <typename I, typename O>
  329. inline
  330. O move_if_noexcept_dispatch(I first, I last, O dst,
  331. std::false_type /*use_move*/)
  332. {
  333. return varray_detail::copy(first, last, dst);
  334. }
  335. template <typename I, typename O>
  336. inline
  337. O move_if_noexcept(I first, I last, O dst)
  338. {
  339. typedef std::is_nothrow_move_constructible<
  340. typename ::boost::iterator_value<O>::type
  341. > use_move;
  342. return move_if_noexcept_dispatch(first, last, dst, use_move()); // may throw
  343. }
  344. // uninitialized_fill(I, I)
  345. template <typename I>
  346. inline
  347. void uninitialized_fill_dispatch(I /*first*/, I /*last*/,
  348. std::true_type const& /*has_trivial_constructor*/,
  349. std::true_type const& /*disable_trivial_init*/)
  350. {}
  351. template <typename I>
  352. inline
  353. void uninitialized_fill_dispatch(I first, I last,
  354. std::true_type const& /*has_trivial_constructor*/,
  355. std::false_type const& /*disable_trivial_init*/)
  356. {
  357. typedef typename boost::iterator_value<I>::type value_type;
  358. for ( ; first != last ; ++first )
  359. new (boost::addressof(*first)) value_type();
  360. }
  361. template <typename I, typename DisableTrivialInit>
  362. inline
  363. void uninitialized_fill_dispatch(I first, I last,
  364. std::false_type const& /*has_trivial_constructor*/,
  365. DisableTrivialInit const& /*not_used*/)
  366. {
  367. typedef typename boost::iterator_value<I>::type value_type;
  368. I it = first;
  369. BOOST_TRY
  370. {
  371. for ( ; it != last ; ++it )
  372. new (boost::addressof(*it)) value_type(); // may throw
  373. }
  374. BOOST_CATCH(...)
  375. {
  376. varray_detail::destroy(first, it);
  377. BOOST_RETHROW;
  378. }
  379. BOOST_CATCH_END
  380. }
  381. template <typename I, typename DisableTrivialInit>
  382. inline
  383. void uninitialized_fill(I first, I last, DisableTrivialInit const& disable_trivial_init)
  384. {
  385. typedef typename boost::iterator_value<I>::type value_type;
  386. uninitialized_fill_dispatch(first, last, std::is_trivially_constructible<value_type>(), disable_trivial_init); // may throw
  387. }
  388. // construct(I)
  389. template <typename I>
  390. inline
  391. void construct_dispatch(std::true_type /*dont_init*/, I /*pos*/)
  392. {}
  393. template <typename I>
  394. inline
  395. void construct_dispatch(std::false_type /*dont_init*/, I pos)
  396. {
  397. typedef typename ::boost::iterator_value<I>::type value_type;
  398. new (static_cast<void*>(boost::addressof(*pos))) value_type(); // may throw
  399. }
  400. template <typename DisableTrivialInit, typename I>
  401. inline
  402. void construct(DisableTrivialInit const&, I pos)
  403. {
  404. typedef typename ::boost::iterator_value<I>::type value_type;
  405. typedef std::integral_constant
  406. <
  407. bool,
  408. std::is_trivially_constructible<value_type>::value
  409. &&
  410. DisableTrivialInit::value
  411. > dont_init;
  412. construct_dispatch(dont_init(), pos); // may throw
  413. }
  414. // construct(I, V)
  415. template <typename I, typename V>
  416. inline
  417. void construct_copy_dispatch(I pos, V const& v,
  418. std::true_type /*use_memcpy*/)
  419. {
  420. ::memcpy(boost::addressof(*pos), boost::addressof(v), sizeof(V));
  421. }
  422. template <typename I, typename P>
  423. inline
  424. void construct_copy_dispatch(I pos, P const& p,
  425. std::false_type const& /*use_memcpy*/)
  426. {
  427. typedef typename boost::iterator_value<I>::type V;
  428. new (static_cast<void*>(boost::addressof(*pos))) V(p); // may throw
  429. }
  430. template <typename DisableTrivialInit, typename I, typename P>
  431. inline
  432. void construct(DisableTrivialInit const&,
  433. I pos, P const& p)
  434. {
  435. construct_copy_dispatch(pos, p, is_memop_safe_for_value<I, P>()); // may throw
  436. }
  437. // Needed by push_back(V &&)
  438. template <typename I, typename V>
  439. inline
  440. void construct_move_dispatch(I pos, V const& v,
  441. std::true_type const& /*use_memcpy*/)
  442. {
  443. ::memcpy(boost::addressof(*pos), boost::addressof(v), sizeof(V));
  444. }
  445. template <typename I, typename P>
  446. inline
  447. void construct_move_dispatch(I pos, P&& p,
  448. std::false_type const& /*use_memcpy*/)
  449. {
  450. typedef typename boost::iterator_value<I>::type V;
  451. new (static_cast<void*>(boost::addressof(*pos))) V(std::move(p)); // may throw
  452. }
  453. template <typename DisableTrivialInit, typename I, typename P>
  454. inline
  455. void construct(DisableTrivialInit const&, I pos, P&& p)
  456. {
  457. construct_move_dispatch(pos, std::move(p), is_memop_safe_for_value<I, P>()); // may throw
  458. }
  459. // Needed by emplace_back() and emplace()
  460. template <typename DisableTrivialInit, typename I, class ...Args>
  461. inline
  462. void construct(DisableTrivialInit const&,
  463. I pos,
  464. Args&& ...args)
  465. {
  466. typedef typename boost::iterator_value<I>::type V;
  467. new (static_cast<void*>(boost::addressof(*pos))) V(std::forward<Args>(args)...); // may throw
  468. }
  469. // assign(I, V)
  470. template <typename I, typename V>
  471. inline
  472. void assign_copy_dispatch(I pos, V const& v,
  473. std::true_type /*use_memcpy*/)
  474. {
  475. // TODO - use memmove here?
  476. ::memcpy(boost::addressof(*pos), boost::addressof(v), sizeof(V));
  477. }
  478. template <typename I, typename V>
  479. inline
  480. void assign_copy_dispatch(I pos, V const& v,
  481. std::false_type /*use_memcpy*/)
  482. {
  483. *pos = v; // may throw
  484. }
  485. template <typename I, typename V>
  486. inline
  487. void assign(I pos, V const& v)
  488. {
  489. assign_copy_dispatch(pos, v, is_memop_safe_for_value<I, V>()); // may throw
  490. }
  491. template <typename I, typename V>
  492. inline
  493. void assign_move_dispatch(I pos, V const& v,
  494. std::true_type /*use_memcpy*/)
  495. {
  496. // TODO - use memmove here?
  497. ::memcpy(boost::addressof(*pos), boost::addressof(v), sizeof(V));
  498. }
  499. template <typename I, typename V>
  500. inline
  501. void assign_move_dispatch(I pos, V&& v,
  502. std::false_type /*use_memcpy*/)
  503. {
  504. *pos = std::move(v); // may throw
  505. }
  506. template <typename I, typename V>
  507. inline
  508. void assign(I pos, V&& v)
  509. {
  510. assign_move_dispatch(pos, std::move(v), is_memop_safe_for_value<I, V>());
  511. }
  512. // uninitialized_copy_s
  513. template <typename I, typename F>
  514. inline std::size_t uninitialized_copy_s(I first, I last, F dest, std::size_t max_count)
  515. {
  516. std::size_t count = 0;
  517. F it = dest;
  518. BOOST_TRY
  519. {
  520. for ( ; first != last ; ++it, ++first, ++count )
  521. {
  522. if ( max_count <= count )
  523. return (std::numeric_limits<std::size_t>::max)();
  524. // dummy 0 as DisableTrivialInit
  525. construct(0, it, *first); // may throw
  526. }
  527. }
  528. BOOST_CATCH(...)
  529. {
  530. varray_detail::destroy(dest, it);
  531. BOOST_RETHROW;
  532. }
  533. BOOST_CATCH_END
  534. return count;
  535. }
  536. // scoped_destructor
  537. template<class T>
  538. class scoped_destructor
  539. {
  540. public:
  541. scoped_destructor(T * ptr) : m_ptr(ptr) {}
  542. ~scoped_destructor()
  543. {
  544. if(m_ptr)
  545. varray_detail::destroy(m_ptr);
  546. }
  547. void release() { m_ptr = 0; }
  548. private:
  549. T * m_ptr;
  550. };
  551. }}}}} // namespace boost::geometry::index::detail::varray_detail
  552. #endif // BOOST_GEOMETRY_INDEX_DETAIL_VARRAY_DETAIL_HPP