]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/boost/poly_collection/detail/type_info_map.hpp
update sources to v12.2.3
[ceph.git] / ceph / src / boost / boost / poly_collection / detail / type_info_map.hpp
1 /* Copyright 2016-2017 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/poly_collection for library home page.
7 */
8
9 #ifndef BOOST_POLY_COLLECTION_DETAIL_TYPE_INFO_MAP_HPP
10 #define BOOST_POLY_COLLECTION_DETAIL_TYPE_INFO_MAP_HPP
11
12 #if defined(_MSC_VER)
13 #pragma once
14 #endif
15
16 #include <boost/detail/workaround.hpp>
17 #include <boost/poly_collection/detail/newdelete_allocator.hpp>
18 #include <functional>
19 #include <typeinfo>
20 #include <unordered_map>
21 #include <utility>
22
23 namespace boost{
24
25 namespace poly_collection{
26
27 namespace detail{
28
29 /* To cope with dynamic modules/libs, the standard allows for different
30 * std::type_info instances to describe the same type, which implies that
31 * std::type_info::operator== and std::type_info::hash_code are costly
32 * operations typically relying on the stored type name.
33 * type_info_ptr_hash<T> behaves roughly as a
34 * std::unordered_map<std::type_index,T> but maintains an internal cache of
35 * passed std::type_info instances so that lookup is performed (when there's a
36 * cache hit) without invoking std::type_info equality and hashing ops.
37 */
38
39 struct type_info_ptr_hash
40 {
41 std::size_t operator()(const std::type_info* p)const noexcept
42 {return p->hash_code();}
43 };
44
45 struct type_info_ptr_equal_to
46 {
47 bool operator()(
48 const std::type_info* p,const std::type_info* q)const noexcept
49 {return *p==*q;}
50 };
51
52
53 template<typename T,typename Allocator>
54 class type_info_map
55 {
56 using map_type=std::unordered_map<
57 const std::type_info*,T,
58 type_info_ptr_hash,type_info_ptr_equal_to,
59 typename std::allocator_traits<Allocator>::template
60 rebind_alloc<std::pair<const std::type_info* const,T>>
61 >;
62
63 public:
64 using key_type=std::type_info;
65 using mapped_type=T;
66 using value_type=typename map_type::value_type;
67 using allocator_type=typename map_type::allocator_type;
68 using iterator=typename map_type::iterator;
69 using const_iterator=typename map_type::const_iterator;
70
71 #if BOOST_WORKAROUND(BOOST_LIBSTDCXX_VERSION,<40900)
72 /* std::unordered_map(const unordered_map&,const allocator_type&),
73 * std::unordered_map(unordered_map&&,const allocator_type&) and
74 * std::unordered_map(const allocator_type&) not available.
75 */
76
77 #define BOOST_POLY_COLLECTION_MAP_CONT_ALLOC_CTOR(x,al) \
78 x.begin(),x.end(), \
79 0,typename map_type::hasher{},typename map_type::key_equal{},al
80 #define BOOST_POLY_COLLECTION_MAP_ALLOC_CTOR(al) \
81 10,typename map_type::hasher{},typename map_type::key_equal{},al
82 #define BOOST_POLY_COLLECTION_CACHE_ALLOC_CTOR(al) \
83 10,typename cache_type::hasher{},typename cache_type::key_equal{},al
84
85 #else
86
87 #define BOOST_POLY_COLLECTION_MAP_CONT_ALLOC_CTOR(x,al) x,al
88 #define BOOST_POLY_COLLECTION_MAP_ALLOC_CTOR(al) al
89 #define BOOST_POLY_COLLECTION_CACHE_ALLOC_CTOR(al) al
90
91 #endif
92
93 type_info_map()=default;
94 type_info_map(const type_info_map& x):
95 map{x.map},
96 cache{BOOST_POLY_COLLECTION_CACHE_ALLOC_CTOR(x.cache.get_allocator())}
97 {build_cache(x.cache);}
98 type_info_map(type_info_map&& x)=default;
99 type_info_map(const allocator_type& al):
100 map{BOOST_POLY_COLLECTION_MAP_ALLOC_CTOR(al)},
101 cache{BOOST_POLY_COLLECTION_CACHE_ALLOC_CTOR(cache_allocator_type{al})}
102 {}
103 type_info_map(const type_info_map& x,const allocator_type& al):
104 map{BOOST_POLY_COLLECTION_MAP_CONT_ALLOC_CTOR(x.map,al)},
105 cache{BOOST_POLY_COLLECTION_CACHE_ALLOC_CTOR(cache_allocator_type{al})}
106 {build_cache(x.cache);}
107 type_info_map(type_info_map&& x,const allocator_type& al):
108 map{BOOST_POLY_COLLECTION_MAP_CONT_ALLOC_CTOR(std::move(x.map),al)},
109 cache{BOOST_POLY_COLLECTION_CACHE_ALLOC_CTOR(cache_allocator_type{al})}
110 {
111 if(al==x.map.get_allocator()&&
112 cache_allocator_type{al}==x.cache.get_allocator()){
113 cache=std::move(x.cache);
114 }
115 else{
116 build_cache(x.cache);
117 x.cache.clear();
118 }
119 }
120
121 #undef BOOST_POLY_COLLECTION_MAP_CONT_ALLOC_CTOR
122 #undef BOOST_POLY_COLLECTION_MAP_ALLOC_CTOR
123 #undef BOOST_POLY_COLLECTION_CACHE_ALLOC_CTOR
124
125 type_info_map& operator=(const type_info_map& x)
126 {
127 if(this!=&x){
128 type_info_map c{x};
129 swap(c);
130 }
131 return *this;
132 }
133
134 type_info_map& operator=(type_info_map&& x)=default;
135
136 allocator_type get_allocator()const noexcept{return map.get_allocator();}
137
138 iterator begin()noexcept{return map.begin();}
139 iterator end()noexcept{return map.end();}
140 const_iterator begin()const noexcept{return map.begin();}
141 const_iterator end()const noexcept{return map.end();}
142 const_iterator cbegin()const noexcept{return map.cbegin();}
143 const_iterator cend()const noexcept{return map.cend();}
144
145 iterator find(const key_type& key)
146 {
147 auto cit=cache.find(&key);
148 if(cit!=cache.end())return cit->second;
149 auto mit=map.find(&key);
150 if(mit!=map.end())cache.insert({&key,mit});
151 return mit;
152 }
153
154 const_iterator find(const key_type& key)const
155 {
156 auto cit=cache.find(&key);
157 if(cit!=cache.end())return cit->second;
158 return map.find(&key);
159 }
160
161 template<typename P>
162 std::pair<iterator,bool> insert(const key_type& key,P&& x)
163 {
164 auto p=map.insert({&key,std::forward<P>(x)});
165 cache.insert({&key,p.first});
166 return p;
167 }
168
169 void swap(type_info_map& x){map.swap(x.map);cache.swap(x.cache);}
170
171 private:
172 using cache_type=std::unordered_map<
173 const std::type_info*,iterator,
174 std::hash<const std::type_info*>,std::equal_to<const std::type_info*>,
175 newdelete_allocator_adaptor<
176 typename std::allocator_traits<Allocator>::template
177 rebind_alloc<std::pair<const std::type_info* const,iterator>>
178 >
179 >;
180 using cache_allocator_type=typename cache_type::allocator_type;
181
182 void build_cache(const cache_type& x)
183 {
184 for(const auto& p:x)cache.insert({p.first,map.find(p.first)});
185 }
186
187 map_type map;
188 cache_type cache;
189 };
190
191 template<typename T,typename Allocator>
192 void swap(type_info_map<T,Allocator>& x,type_info_map<T,Allocator>& y)
193 {
194 x.swap(y);
195 }
196
197 } /* namespace poly_collection::detail */
198
199 } /* namespace poly_collection */
200
201 } /* namespace boost */
202
203 #endif