copy_map.hpp 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151
  1. /* Copyright 2003-2018 Joaquin M Lopez Munoz.
  2. * Distributed under the Boost Software License, Version 1.0.
  3. * (See accompanying file LICENSE_1_0.txt or copy at
  4. * http://www.boost.org/LICENSE_1_0.txt)
  5. *
  6. * See http://www.boost.org/libs/multi_index for library home page.
  7. */
  8. #ifndef BOOST_MULTI_INDEX_DETAIL_COPY_MAP_HPP
  9. #define BOOST_MULTI_INDEX_DETAIL_COPY_MAP_HPP
  10. #if defined(_MSC_VER)
  11. #pragma once
  12. #endif
  13. #include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
  14. #include <algorithm>
  15. #include <boost/core/addressof.hpp>
  16. #include <boost/detail/no_exceptions_support.hpp>
  17. #include <boost/multi_index/detail/allocator_traits.hpp>
  18. #include <boost/multi_index/detail/auto_space.hpp>
  19. #include <boost/multi_index/detail/raw_ptr.hpp>
  20. #include <boost/noncopyable.hpp>
  21. #include <functional>
  22. namespace boost{
  23. namespace multi_index{
  24. namespace detail{
  25. /* copy_map is used as an auxiliary structure during copy_() operations.
  26. * When a container with n nodes is replicated, node_map holds the pairings
  27. * between original and copied nodes, and provides a fast way to find a
  28. * copied node from an original one.
  29. * The semantics of the class are not simple, and no attempt has been made
  30. * to enforce it: multi_index_container handles it right. On the other hand,
  31. * the const interface, which is the one provided to index implementations,
  32. * only allows for:
  33. * - Enumeration of pairs of (original,copied) nodes (excluding the headers),
  34. * - fast retrieval of copied nodes (including the headers.)
  35. */
  36. template <typename Node>
  37. struct copy_map_entry
  38. {
  39. copy_map_entry(Node* f,Node* s):first(f),second(s){}
  40. Node* first;
  41. Node* second;
  42. bool operator<(const copy_map_entry<Node>& x)const
  43. {
  44. return std::less<Node*>()(first,x.first);
  45. }
  46. };
  47. template <typename Node,typename Allocator>
  48. class copy_map:private noncopyable
  49. {
  50. typedef typename rebind_alloc_for<
  51. Allocator,Node
  52. >::type allocator_type;
  53. typedef allocator_traits<allocator_type> alloc_traits;
  54. typedef typename alloc_traits::pointer pointer;
  55. public:
  56. typedef const copy_map_entry<Node>* const_iterator;
  57. typedef typename alloc_traits::size_type size_type;
  58. copy_map(
  59. const Allocator& al,size_type size,Node* header_org,Node* header_cpy):
  60. al_(al),size_(size),spc(al_,size_),n(0),
  61. header_org_(header_org),header_cpy_(header_cpy),released(false)
  62. {}
  63. ~copy_map()
  64. {
  65. if(!released){
  66. for(size_type i=0;i<n;++i){
  67. alloc_traits::destroy(
  68. al_,boost::addressof((spc.data()+i)->second->value()));
  69. deallocate((spc.data()+i)->second);
  70. }
  71. }
  72. }
  73. const_iterator begin()const{return raw_ptr<const_iterator>(spc.data());}
  74. const_iterator end()const{return raw_ptr<const_iterator>(spc.data()+n);}
  75. void clone(Node* node)
  76. {
  77. (spc.data()+n)->first=node;
  78. (spc.data()+n)->second=raw_ptr<Node*>(allocate());
  79. BOOST_TRY{
  80. alloc_traits::construct(
  81. al_,boost::addressof((spc.data()+n)->second->value()),node->value());
  82. }
  83. BOOST_CATCH(...){
  84. deallocate((spc.data()+n)->second);
  85. BOOST_RETHROW;
  86. }
  87. BOOST_CATCH_END
  88. ++n;
  89. if(n==size_){
  90. std::sort(
  91. raw_ptr<copy_map_entry<Node>*>(spc.data()),
  92. raw_ptr<copy_map_entry<Node>*>(spc.data())+size_);
  93. }
  94. }
  95. Node* find(Node* node)const
  96. {
  97. if(node==header_org_)return header_cpy_;
  98. return std::lower_bound(
  99. begin(),end(),copy_map_entry<Node>(node,0))->second;
  100. }
  101. void release()
  102. {
  103. released=true;
  104. }
  105. private:
  106. allocator_type al_;
  107. size_type size_;
  108. auto_space<copy_map_entry<Node>,Allocator> spc;
  109. size_type n;
  110. Node* header_org_;
  111. Node* header_cpy_;
  112. bool released;
  113. pointer allocate()
  114. {
  115. return alloc_traits::allocate(al_,1);
  116. }
  117. void deallocate(Node* node)
  118. {
  119. alloc_traits::deallocate(al_,static_cast<pointer>(node),1);
  120. }
  121. };
  122. } /* namespace multi_index::detail */
  123. } /* namespace multi_index */
  124. } /* namespace boost */
  125. #endif