annotate libstdc++-v3/include/bits/hashtable.h @ 131:84e7813d76e9

gcc-8.2
author mir3636
date Thu, 25 Oct 2018 07:37:49 +0900
parents 04ced10e8804
children 1830386684a0
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
111
kono
parents:
diff changeset
1 // hashtable.h header -*- C++ -*-
kono
parents:
diff changeset
2
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3 // Copyright (C) 2007-2018 Free Software Foundation, Inc.
111
kono
parents:
diff changeset
4 //
kono
parents:
diff changeset
5 // This file is part of the GNU ISO C++ Library. This library is free
kono
parents:
diff changeset
6 // software; you can redistribute it and/or modify it under the
kono
parents:
diff changeset
7 // terms of the GNU General Public License as published by the
kono
parents:
diff changeset
8 // Free Software Foundation; either version 3, or (at your option)
kono
parents:
diff changeset
9 // any later version.
kono
parents:
diff changeset
10
kono
parents:
diff changeset
11 // This library is distributed in the hope that it will be useful,
kono
parents:
diff changeset
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
kono
parents:
diff changeset
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
kono
parents:
diff changeset
14 // GNU General Public License for more details.
kono
parents:
diff changeset
15
kono
parents:
diff changeset
16 // Under Section 7 of GPL version 3, you are granted additional
kono
parents:
diff changeset
17 // permissions described in the GCC Runtime Library Exception, version
kono
parents:
diff changeset
18 // 3.1, as published by the Free Software Foundation.
kono
parents:
diff changeset
19
kono
parents:
diff changeset
20 // You should have received a copy of the GNU General Public License and
kono
parents:
diff changeset
21 // a copy of the GCC Runtime Library Exception along with this program;
kono
parents:
diff changeset
22 // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
kono
parents:
diff changeset
23 // <http://www.gnu.org/licenses/>.
kono
parents:
diff changeset
24
kono
parents:
diff changeset
25 /** @file bits/hashtable.h
kono
parents:
diff changeset
26 * This is an internal header file, included by other library headers.
kono
parents:
diff changeset
27 * Do not attempt to use it directly. @headername{unordered_map, unordered_set}
kono
parents:
diff changeset
28 */
kono
parents:
diff changeset
29
kono
parents:
diff changeset
30 #ifndef _HASHTABLE_H
kono
parents:
diff changeset
31 #define _HASHTABLE_H 1
kono
parents:
diff changeset
32
kono
parents:
diff changeset
33 #pragma GCC system_header
kono
parents:
diff changeset
34
kono
parents:
diff changeset
35 #include <bits/hashtable_policy.h>
kono
parents:
diff changeset
36 #if __cplusplus > 201402L
kono
parents:
diff changeset
37 # include <bits/node_handle.h>
kono
parents:
diff changeset
38 #endif
kono
parents:
diff changeset
39
kono
parents:
diff changeset
40 namespace std _GLIBCXX_VISIBILITY(default)
kono
parents:
diff changeset
41 {
kono
parents:
diff changeset
42 _GLIBCXX_BEGIN_NAMESPACE_VERSION
kono
parents:
diff changeset
43
kono
parents:
diff changeset
44 template<typename _Tp, typename _Hash>
kono
parents:
diff changeset
45 using __cache_default
kono
parents:
diff changeset
46 = __not_<__and_<// Do not cache for fast hasher.
kono
parents:
diff changeset
47 __is_fast_hash<_Hash>,
kono
parents:
diff changeset
48 // Mandatory to have erase not throwing.
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
49 __is_nothrow_invocable<const _Hash&, const _Tp&>>>;
111
kono
parents:
diff changeset
50
kono
parents:
diff changeset
51 /**
kono
parents:
diff changeset
52 * Primary class template _Hashtable.
kono
parents:
diff changeset
53 *
kono
parents:
diff changeset
54 * @ingroup hashtable-detail
kono
parents:
diff changeset
55 *
kono
parents:
diff changeset
56 * @tparam _Value CopyConstructible type.
kono
parents:
diff changeset
57 *
kono
parents:
diff changeset
58 * @tparam _Key CopyConstructible type.
kono
parents:
diff changeset
59 *
kono
parents:
diff changeset
60 * @tparam _Alloc An allocator type
kono
parents:
diff changeset
61 * ([lib.allocator.requirements]) whose _Alloc::value_type is
kono
parents:
diff changeset
62 * _Value. As a conforming extension, we allow for
kono
parents:
diff changeset
63 * _Alloc::value_type != _Value.
kono
parents:
diff changeset
64 *
kono
parents:
diff changeset
65 * @tparam _ExtractKey Function object that takes an object of type
kono
parents:
diff changeset
66 * _Value and returns a value of type _Key.
kono
parents:
diff changeset
67 *
kono
parents:
diff changeset
68 * @tparam _Equal Function object that takes two objects of type k
kono
parents:
diff changeset
69 * and returns a bool-like value that is true if the two objects
kono
parents:
diff changeset
70 * are considered equal.
kono
parents:
diff changeset
71 *
kono
parents:
diff changeset
72 * @tparam _H1 The hash function. A unary function object with
kono
parents:
diff changeset
73 * argument type _Key and result type size_t. Return values should
kono
parents:
diff changeset
74 * be distributed over the entire range [0, numeric_limits<size_t>:::max()].
kono
parents:
diff changeset
75 *
kono
parents:
diff changeset
76 * @tparam _H2 The range-hashing function (in the terminology of
kono
parents:
diff changeset
77 * Tavori and Dreizin). A binary function object whose argument
kono
parents:
diff changeset
78 * types and result type are all size_t. Given arguments r and N,
kono
parents:
diff changeset
79 * the return value is in the range [0, N).
kono
parents:
diff changeset
80 *
kono
parents:
diff changeset
81 * @tparam _Hash The ranged hash function (Tavori and Dreizin). A
kono
parents:
diff changeset
82 * binary function whose argument types are _Key and size_t and
kono
parents:
diff changeset
83 * whose result type is size_t. Given arguments k and N, the
kono
parents:
diff changeset
84 * return value is in the range [0, N). Default: hash(k, N) =
kono
parents:
diff changeset
85 * h2(h1(k), N). If _Hash is anything other than the default, _H1
kono
parents:
diff changeset
86 * and _H2 are ignored.
kono
parents:
diff changeset
87 *
kono
parents:
diff changeset
88 * @tparam _RehashPolicy Policy class with three members, all of
kono
parents:
diff changeset
89 * which govern the bucket count. _M_next_bkt(n) returns a bucket
kono
parents:
diff changeset
90 * count no smaller than n. _M_bkt_for_elements(n) returns a
kono
parents:
diff changeset
91 * bucket count appropriate for an element count of n.
kono
parents:
diff changeset
92 * _M_need_rehash(n_bkt, n_elt, n_ins) determines whether, if the
kono
parents:
diff changeset
93 * current bucket count is n_bkt and the current element count is
kono
parents:
diff changeset
94 * n_elt, we need to increase the bucket count. If so, returns
kono
parents:
diff changeset
95 * make_pair(true, n), where n is the new bucket count. If not,
kono
parents:
diff changeset
96 * returns make_pair(false, <anything>)
kono
parents:
diff changeset
97 *
kono
parents:
diff changeset
98 * @tparam _Traits Compile-time class with three boolean
kono
parents:
diff changeset
99 * std::integral_constant members: __cache_hash_code, __constant_iterators,
kono
parents:
diff changeset
100 * __unique_keys.
kono
parents:
diff changeset
101 *
kono
parents:
diff changeset
102 * Each _Hashtable data structure has:
kono
parents:
diff changeset
103 *
kono
parents:
diff changeset
104 * - _Bucket[] _M_buckets
kono
parents:
diff changeset
105 * - _Hash_node_base _M_before_begin
kono
parents:
diff changeset
106 * - size_type _M_bucket_count
kono
parents:
diff changeset
107 * - size_type _M_element_count
kono
parents:
diff changeset
108 *
kono
parents:
diff changeset
109 * with _Bucket being _Hash_node* and _Hash_node containing:
kono
parents:
diff changeset
110 *
kono
parents:
diff changeset
111 * - _Hash_node* _M_next
kono
parents:
diff changeset
112 * - Tp _M_value
kono
parents:
diff changeset
113 * - size_t _M_hash_code if cache_hash_code is true
kono
parents:
diff changeset
114 *
kono
parents:
diff changeset
115 * In terms of Standard containers the hashtable is like the aggregation of:
kono
parents:
diff changeset
116 *
kono
parents:
diff changeset
117 * - std::forward_list<_Node> containing the elements
kono
parents:
diff changeset
118 * - std::vector<std::forward_list<_Node>::iterator> representing the buckets
kono
parents:
diff changeset
119 *
kono
parents:
diff changeset
120 * The non-empty buckets contain the node before the first node in the
kono
parents:
diff changeset
121 * bucket. This design makes it possible to implement something like a
kono
parents:
diff changeset
122 * std::forward_list::insert_after on container insertion and
kono
parents:
diff changeset
123 * std::forward_list::erase_after on container erase
kono
parents:
diff changeset
124 * calls. _M_before_begin is equivalent to
kono
parents:
diff changeset
125 * std::forward_list::before_begin. Empty buckets contain
kono
parents:
diff changeset
126 * nullptr. Note that one of the non-empty buckets contains
kono
parents:
diff changeset
127 * &_M_before_begin which is not a dereferenceable node so the
kono
parents:
diff changeset
128 * node pointer in a bucket shall never be dereferenced, only its
kono
parents:
diff changeset
129 * next node can be.
kono
parents:
diff changeset
130 *
kono
parents:
diff changeset
131 * Walking through a bucket's nodes requires a check on the hash code to
kono
parents:
diff changeset
132 * see if each node is still in the bucket. Such a design assumes a
kono
parents:
diff changeset
133 * quite efficient hash functor and is one of the reasons it is
kono
parents:
diff changeset
134 * highly advisable to set __cache_hash_code to true.
kono
parents:
diff changeset
135 *
kono
parents:
diff changeset
136 * The container iterators are simply built from nodes. This way
kono
parents:
diff changeset
137 * incrementing the iterator is perfectly efficient independent of
kono
parents:
diff changeset
138 * how many empty buckets there are in the container.
kono
parents:
diff changeset
139 *
kono
parents:
diff changeset
140 * On insert we compute the element's hash code and use it to find the
kono
parents:
diff changeset
141 * bucket index. If the element must be inserted in an empty bucket
kono
parents:
diff changeset
142 * we add it at the beginning of the singly linked list and make the
kono
parents:
diff changeset
143 * bucket point to _M_before_begin. The bucket that used to point to
kono
parents:
diff changeset
144 * _M_before_begin, if any, is updated to point to its new before
kono
parents:
diff changeset
145 * begin node.
kono
parents:
diff changeset
146 *
kono
parents:
diff changeset
147 * On erase, the simple iterator design requires using the hash
kono
parents:
diff changeset
148 * functor to get the index of the bucket to update. For this
kono
parents:
diff changeset
149 * reason, when __cache_hash_code is set to false the hash functor must
kono
parents:
diff changeset
150 * not throw and this is enforced by a static assertion.
kono
parents:
diff changeset
151 *
kono
parents:
diff changeset
152 * Functionality is implemented by decomposition into base classes,
kono
parents:
diff changeset
153 * where the derived _Hashtable class is used in _Map_base,
kono
parents:
diff changeset
154 * _Insert, _Rehash_base, and _Equality base classes to access the
kono
parents:
diff changeset
155 * "this" pointer. _Hashtable_base is used in the base classes as a
kono
parents:
diff changeset
156 * non-recursive, fully-completed-type so that detailed nested type
kono
parents:
diff changeset
157 * information, such as iterator type and node type, can be
kono
parents:
diff changeset
158 * used. This is similar to the "Curiously Recurring Template
kono
parents:
diff changeset
159 * Pattern" (CRTP) technique, but uses a reconstructed, not
kono
parents:
diff changeset
160 * explicitly passed, template pattern.
kono
parents:
diff changeset
161 *
kono
parents:
diff changeset
162 * Base class templates are:
kono
parents:
diff changeset
163 * - __detail::_Hashtable_base
kono
parents:
diff changeset
164 * - __detail::_Map_base
kono
parents:
diff changeset
165 * - __detail::_Insert
kono
parents:
diff changeset
166 * - __detail::_Rehash_base
kono
parents:
diff changeset
167 * - __detail::_Equality
kono
parents:
diff changeset
168 */
kono
parents:
diff changeset
169 template<typename _Key, typename _Value, typename _Alloc,
kono
parents:
diff changeset
170 typename _ExtractKey, typename _Equal,
kono
parents:
diff changeset
171 typename _H1, typename _H2, typename _Hash,
kono
parents:
diff changeset
172 typename _RehashPolicy, typename _Traits>
kono
parents:
diff changeset
173 class _Hashtable
kono
parents:
diff changeset
174 : public __detail::_Hashtable_base<_Key, _Value, _ExtractKey, _Equal,
kono
parents:
diff changeset
175 _H1, _H2, _Hash, _Traits>,
kono
parents:
diff changeset
176 public __detail::_Map_base<_Key, _Value, _Alloc, _ExtractKey, _Equal,
kono
parents:
diff changeset
177 _H1, _H2, _Hash, _RehashPolicy, _Traits>,
kono
parents:
diff changeset
178 public __detail::_Insert<_Key, _Value, _Alloc, _ExtractKey, _Equal,
kono
parents:
diff changeset
179 _H1, _H2, _Hash, _RehashPolicy, _Traits>,
kono
parents:
diff changeset
180 public __detail::_Rehash_base<_Key, _Value, _Alloc, _ExtractKey, _Equal,
kono
parents:
diff changeset
181 _H1, _H2, _Hash, _RehashPolicy, _Traits>,
kono
parents:
diff changeset
182 public __detail::_Equality<_Key, _Value, _Alloc, _ExtractKey, _Equal,
kono
parents:
diff changeset
183 _H1, _H2, _Hash, _RehashPolicy, _Traits>,
kono
parents:
diff changeset
184 private __detail::_Hashtable_alloc<
kono
parents:
diff changeset
185 __alloc_rebind<_Alloc,
kono
parents:
diff changeset
186 __detail::_Hash_node<_Value,
kono
parents:
diff changeset
187 _Traits::__hash_cached::value>>>
kono
parents:
diff changeset
188 {
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
189 static_assert(is_same<typename remove_cv<_Value>::type, _Value>::value,
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
190 "unordered container must have a non-const, non-volatile value_type");
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
191 #ifdef __STRICT_ANSI__
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
192 static_assert(is_same<typename _Alloc::value_type, _Value>{},
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
193 "unordered container must have the same value_type as its allocator");
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
194 #endif
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
195 static_assert(__is_invocable<const _H1&, const _Key&>{},
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
196 "hash function must be invocable with an argument of key type");
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
197 static_assert(__is_invocable<const _Equal&, const _Key&, const _Key&>{},
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
198 "key equality predicate must be invocable with two arguments of "
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
199 "key type");
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
200
111
kono
parents:
diff changeset
201 using __traits_type = _Traits;
kono
parents:
diff changeset
202 using __hash_cached = typename __traits_type::__hash_cached;
kono
parents:
diff changeset
203 using __node_type = __detail::_Hash_node<_Value, __hash_cached::value>;
kono
parents:
diff changeset
204 using __node_alloc_type = __alloc_rebind<_Alloc, __node_type>;
kono
parents:
diff changeset
205
kono
parents:
diff changeset
206 using __hashtable_alloc = __detail::_Hashtable_alloc<__node_alloc_type>;
kono
parents:
diff changeset
207
kono
parents:
diff changeset
208 using __value_alloc_traits =
kono
parents:
diff changeset
209 typename __hashtable_alloc::__value_alloc_traits;
kono
parents:
diff changeset
210 using __node_alloc_traits =
kono
parents:
diff changeset
211 typename __hashtable_alloc::__node_alloc_traits;
kono
parents:
diff changeset
212 using __node_base = typename __hashtable_alloc::__node_base;
kono
parents:
diff changeset
213 using __bucket_type = typename __hashtable_alloc::__bucket_type;
kono
parents:
diff changeset
214
kono
parents:
diff changeset
215 public:
kono
parents:
diff changeset
216 typedef _Key key_type;
kono
parents:
diff changeset
217 typedef _Value value_type;
kono
parents:
diff changeset
218 typedef _Alloc allocator_type;
kono
parents:
diff changeset
219 typedef _Equal key_equal;
kono
parents:
diff changeset
220
kono
parents:
diff changeset
221 // mapped_type, if present, comes from _Map_base.
kono
parents:
diff changeset
222 // hasher, if present, comes from _Hash_code_base/_Hashtable_base.
kono
parents:
diff changeset
223 typedef typename __value_alloc_traits::pointer pointer;
kono
parents:
diff changeset
224 typedef typename __value_alloc_traits::const_pointer const_pointer;
kono
parents:
diff changeset
225 typedef value_type& reference;
kono
parents:
diff changeset
226 typedef const value_type& const_reference;
kono
parents:
diff changeset
227
kono
parents:
diff changeset
228 private:
kono
parents:
diff changeset
229 using __rehash_type = _RehashPolicy;
kono
parents:
diff changeset
230 using __rehash_state = typename __rehash_type::_State;
kono
parents:
diff changeset
231
kono
parents:
diff changeset
232 using __constant_iterators = typename __traits_type::__constant_iterators;
kono
parents:
diff changeset
233 using __unique_keys = typename __traits_type::__unique_keys;
kono
parents:
diff changeset
234
kono
parents:
diff changeset
235 using __key_extract = typename std::conditional<
kono
parents:
diff changeset
236 __constant_iterators::value,
kono
parents:
diff changeset
237 __detail::_Identity,
kono
parents:
diff changeset
238 __detail::_Select1st>::type;
kono
parents:
diff changeset
239
kono
parents:
diff changeset
240 using __hashtable_base = __detail::
kono
parents:
diff changeset
241 _Hashtable_base<_Key, _Value, _ExtractKey,
kono
parents:
diff changeset
242 _Equal, _H1, _H2, _Hash, _Traits>;
kono
parents:
diff changeset
243
kono
parents:
diff changeset
244 using __hash_code_base = typename __hashtable_base::__hash_code_base;
kono
parents:
diff changeset
245 using __hash_code = typename __hashtable_base::__hash_code;
kono
parents:
diff changeset
246 using __ireturn_type = typename __hashtable_base::__ireturn_type;
kono
parents:
diff changeset
247
kono
parents:
diff changeset
248 using __map_base = __detail::_Map_base<_Key, _Value, _Alloc, _ExtractKey,
kono
parents:
diff changeset
249 _Equal, _H1, _H2, _Hash,
kono
parents:
diff changeset
250 _RehashPolicy, _Traits>;
kono
parents:
diff changeset
251
kono
parents:
diff changeset
252 using __rehash_base = __detail::_Rehash_base<_Key, _Value, _Alloc,
kono
parents:
diff changeset
253 _ExtractKey, _Equal,
kono
parents:
diff changeset
254 _H1, _H2, _Hash,
kono
parents:
diff changeset
255 _RehashPolicy, _Traits>;
kono
parents:
diff changeset
256
kono
parents:
diff changeset
257 using __eq_base = __detail::_Equality<_Key, _Value, _Alloc, _ExtractKey,
kono
parents:
diff changeset
258 _Equal, _H1, _H2, _Hash,
kono
parents:
diff changeset
259 _RehashPolicy, _Traits>;
kono
parents:
diff changeset
260
kono
parents:
diff changeset
261 using __reuse_or_alloc_node_type =
kono
parents:
diff changeset
262 __detail::_ReuseOrAllocNode<__node_alloc_type>;
kono
parents:
diff changeset
263
kono
parents:
diff changeset
264 // Metaprogramming for picking apart hash caching.
kono
parents:
diff changeset
265 template<typename _Cond>
kono
parents:
diff changeset
266 using __if_hash_cached = __or_<__not_<__hash_cached>, _Cond>;
kono
parents:
diff changeset
267
kono
parents:
diff changeset
268 template<typename _Cond>
kono
parents:
diff changeset
269 using __if_hash_not_cached = __or_<__hash_cached, _Cond>;
kono
parents:
diff changeset
270
kono
parents:
diff changeset
271 // Compile-time diagnostics.
kono
parents:
diff changeset
272
kono
parents:
diff changeset
273 // _Hash_code_base has everything protected, so use this derived type to
kono
parents:
diff changeset
274 // access it.
kono
parents:
diff changeset
275 struct __hash_code_base_access : __hash_code_base
kono
parents:
diff changeset
276 { using __hash_code_base::_M_bucket_index; };
kono
parents:
diff changeset
277
kono
parents:
diff changeset
278 // Getting a bucket index from a node shall not throw because it is used
kono
parents:
diff changeset
279 // in methods (erase, swap...) that shall not throw.
kono
parents:
diff changeset
280 static_assert(noexcept(declval<const __hash_code_base_access&>()
kono
parents:
diff changeset
281 ._M_bucket_index((const __node_type*)nullptr,
kono
parents:
diff changeset
282 (std::size_t)0)),
kono
parents:
diff changeset
283 "Cache the hash code or qualify your functors involved"
kono
parents:
diff changeset
284 " in hash code and bucket index computation with noexcept");
kono
parents:
diff changeset
285
kono
parents:
diff changeset
286 // Following two static assertions are necessary to guarantee
kono
parents:
diff changeset
287 // that local_iterator will be default constructible.
kono
parents:
diff changeset
288
kono
parents:
diff changeset
289 // When hash codes are cached local iterator inherits from H2 functor
kono
parents:
diff changeset
290 // which must then be default constructible.
kono
parents:
diff changeset
291 static_assert(__if_hash_cached<is_default_constructible<_H2>>::value,
kono
parents:
diff changeset
292 "Functor used to map hash code to bucket index"
kono
parents:
diff changeset
293 " must be default constructible");
kono
parents:
diff changeset
294
kono
parents:
diff changeset
295 template<typename _Keya, typename _Valuea, typename _Alloca,
kono
parents:
diff changeset
296 typename _ExtractKeya, typename _Equala,
kono
parents:
diff changeset
297 typename _H1a, typename _H2a, typename _Hasha,
kono
parents:
diff changeset
298 typename _RehashPolicya, typename _Traitsa,
kono
parents:
diff changeset
299 bool _Unique_keysa>
kono
parents:
diff changeset
300 friend struct __detail::_Map_base;
kono
parents:
diff changeset
301
kono
parents:
diff changeset
302 template<typename _Keya, typename _Valuea, typename _Alloca,
kono
parents:
diff changeset
303 typename _ExtractKeya, typename _Equala,
kono
parents:
diff changeset
304 typename _H1a, typename _H2a, typename _Hasha,
kono
parents:
diff changeset
305 typename _RehashPolicya, typename _Traitsa>
kono
parents:
diff changeset
306 friend struct __detail::_Insert_base;
kono
parents:
diff changeset
307
kono
parents:
diff changeset
308 template<typename _Keya, typename _Valuea, typename _Alloca,
kono
parents:
diff changeset
309 typename _ExtractKeya, typename _Equala,
kono
parents:
diff changeset
310 typename _H1a, typename _H2a, typename _Hasha,
kono
parents:
diff changeset
311 typename _RehashPolicya, typename _Traitsa,
kono
parents:
diff changeset
312 bool _Constant_iteratorsa>
kono
parents:
diff changeset
313 friend struct __detail::_Insert;
kono
parents:
diff changeset
314
kono
parents:
diff changeset
315 public:
kono
parents:
diff changeset
316 using size_type = typename __hashtable_base::size_type;
kono
parents:
diff changeset
317 using difference_type = typename __hashtable_base::difference_type;
kono
parents:
diff changeset
318
kono
parents:
diff changeset
319 using iterator = typename __hashtable_base::iterator;
kono
parents:
diff changeset
320 using const_iterator = typename __hashtable_base::const_iterator;
kono
parents:
diff changeset
321
kono
parents:
diff changeset
322 using local_iterator = typename __hashtable_base::local_iterator;
kono
parents:
diff changeset
323 using const_local_iterator = typename __hashtable_base::
kono
parents:
diff changeset
324 const_local_iterator;
kono
parents:
diff changeset
325
kono
parents:
diff changeset
326 #if __cplusplus > 201402L
kono
parents:
diff changeset
327 using node_type = _Node_handle<_Key, _Value, __node_alloc_type>;
kono
parents:
diff changeset
328 using insert_return_type = _Node_insert_return<iterator, node_type>;
kono
parents:
diff changeset
329 #endif
kono
parents:
diff changeset
330
kono
parents:
diff changeset
331 private:
kono
parents:
diff changeset
332 __bucket_type* _M_buckets = &_M_single_bucket;
kono
parents:
diff changeset
333 size_type _M_bucket_count = 1;
kono
parents:
diff changeset
334 __node_base _M_before_begin;
kono
parents:
diff changeset
335 size_type _M_element_count = 0;
kono
parents:
diff changeset
336 _RehashPolicy _M_rehash_policy;
kono
parents:
diff changeset
337
kono
parents:
diff changeset
338 // A single bucket used when only need for 1 bucket. Especially
kono
parents:
diff changeset
339 // interesting in move semantic to leave hashtable with only 1 buckets
kono
parents:
diff changeset
340 // which is not allocated so that we can have those operations noexcept
kono
parents:
diff changeset
341 // qualified.
kono
parents:
diff changeset
342 // Note that we can't leave hashtable with 0 bucket without adding
kono
parents:
diff changeset
343 // numerous checks in the code to avoid 0 modulus.
kono
parents:
diff changeset
344 __bucket_type _M_single_bucket = nullptr;
kono
parents:
diff changeset
345
kono
parents:
diff changeset
346 bool
kono
parents:
diff changeset
347 _M_uses_single_bucket(__bucket_type* __bkts) const
kono
parents:
diff changeset
348 { return __builtin_expect(__bkts == &_M_single_bucket, false); }
kono
parents:
diff changeset
349
kono
parents:
diff changeset
350 bool
kono
parents:
diff changeset
351 _M_uses_single_bucket() const
kono
parents:
diff changeset
352 { return _M_uses_single_bucket(_M_buckets); }
kono
parents:
diff changeset
353
kono
parents:
diff changeset
354 __hashtable_alloc&
kono
parents:
diff changeset
355 _M_base_alloc() { return *this; }
kono
parents:
diff changeset
356
kono
parents:
diff changeset
357 __bucket_type*
kono
parents:
diff changeset
358 _M_allocate_buckets(size_type __n)
kono
parents:
diff changeset
359 {
kono
parents:
diff changeset
360 if (__builtin_expect(__n == 1, false))
kono
parents:
diff changeset
361 {
kono
parents:
diff changeset
362 _M_single_bucket = nullptr;
kono
parents:
diff changeset
363 return &_M_single_bucket;
kono
parents:
diff changeset
364 }
kono
parents:
diff changeset
365
kono
parents:
diff changeset
366 return __hashtable_alloc::_M_allocate_buckets(__n);
kono
parents:
diff changeset
367 }
kono
parents:
diff changeset
368
kono
parents:
diff changeset
369 void
kono
parents:
diff changeset
370 _M_deallocate_buckets(__bucket_type* __bkts, size_type __n)
kono
parents:
diff changeset
371 {
kono
parents:
diff changeset
372 if (_M_uses_single_bucket(__bkts))
kono
parents:
diff changeset
373 return;
kono
parents:
diff changeset
374
kono
parents:
diff changeset
375 __hashtable_alloc::_M_deallocate_buckets(__bkts, __n);
kono
parents:
diff changeset
376 }
kono
parents:
diff changeset
377
kono
parents:
diff changeset
378 void
kono
parents:
diff changeset
379 _M_deallocate_buckets()
kono
parents:
diff changeset
380 { _M_deallocate_buckets(_M_buckets, _M_bucket_count); }
kono
parents:
diff changeset
381
kono
parents:
diff changeset
382 // Gets bucket begin, deals with the fact that non-empty buckets contain
kono
parents:
diff changeset
383 // their before begin node.
kono
parents:
diff changeset
384 __node_type*
kono
parents:
diff changeset
385 _M_bucket_begin(size_type __bkt) const;
kono
parents:
diff changeset
386
kono
parents:
diff changeset
387 __node_type*
kono
parents:
diff changeset
388 _M_begin() const
kono
parents:
diff changeset
389 { return static_cast<__node_type*>(_M_before_begin._M_nxt); }
kono
parents:
diff changeset
390
kono
parents:
diff changeset
391 template<typename _NodeGenerator>
kono
parents:
diff changeset
392 void
kono
parents:
diff changeset
393 _M_assign(const _Hashtable&, const _NodeGenerator&);
kono
parents:
diff changeset
394
kono
parents:
diff changeset
395 void
kono
parents:
diff changeset
396 _M_move_assign(_Hashtable&&, std::true_type);
kono
parents:
diff changeset
397
kono
parents:
diff changeset
398 void
kono
parents:
diff changeset
399 _M_move_assign(_Hashtable&&, std::false_type);
kono
parents:
diff changeset
400
kono
parents:
diff changeset
401 void
kono
parents:
diff changeset
402 _M_reset() noexcept;
kono
parents:
diff changeset
403
kono
parents:
diff changeset
404 _Hashtable(const _H1& __h1, const _H2& __h2, const _Hash& __h,
kono
parents:
diff changeset
405 const _Equal& __eq, const _ExtractKey& __exk,
kono
parents:
diff changeset
406 const allocator_type& __a)
kono
parents:
diff changeset
407 : __hashtable_base(__exk, __h1, __h2, __h, __eq),
kono
parents:
diff changeset
408 __hashtable_alloc(__node_alloc_type(__a))
kono
parents:
diff changeset
409 { }
kono
parents:
diff changeset
410
kono
parents:
diff changeset
411 public:
kono
parents:
diff changeset
412 // Constructor, destructor, assignment, swap
kono
parents:
diff changeset
413 _Hashtable() = default;
kono
parents:
diff changeset
414 _Hashtable(size_type __bucket_hint,
kono
parents:
diff changeset
415 const _H1&, const _H2&, const _Hash&,
kono
parents:
diff changeset
416 const _Equal&, const _ExtractKey&,
kono
parents:
diff changeset
417 const allocator_type&);
kono
parents:
diff changeset
418
kono
parents:
diff changeset
419 template<typename _InputIterator>
kono
parents:
diff changeset
420 _Hashtable(_InputIterator __first, _InputIterator __last,
kono
parents:
diff changeset
421 size_type __bucket_hint,
kono
parents:
diff changeset
422 const _H1&, const _H2&, const _Hash&,
kono
parents:
diff changeset
423 const _Equal&, const _ExtractKey&,
kono
parents:
diff changeset
424 const allocator_type&);
kono
parents:
diff changeset
425
kono
parents:
diff changeset
426 _Hashtable(const _Hashtable&);
kono
parents:
diff changeset
427
kono
parents:
diff changeset
428 _Hashtable(_Hashtable&&) noexcept;
kono
parents:
diff changeset
429
kono
parents:
diff changeset
430 _Hashtable(const _Hashtable&, const allocator_type&);
kono
parents:
diff changeset
431
kono
parents:
diff changeset
432 _Hashtable(_Hashtable&&, const allocator_type&);
kono
parents:
diff changeset
433
kono
parents:
diff changeset
434 // Use delegating constructors.
kono
parents:
diff changeset
435 explicit
kono
parents:
diff changeset
436 _Hashtable(const allocator_type& __a)
kono
parents:
diff changeset
437 : __hashtable_alloc(__node_alloc_type(__a))
kono
parents:
diff changeset
438 { }
kono
parents:
diff changeset
439
kono
parents:
diff changeset
440 explicit
kono
parents:
diff changeset
441 _Hashtable(size_type __n,
kono
parents:
diff changeset
442 const _H1& __hf = _H1(),
kono
parents:
diff changeset
443 const key_equal& __eql = key_equal(),
kono
parents:
diff changeset
444 const allocator_type& __a = allocator_type())
kono
parents:
diff changeset
445 : _Hashtable(__n, __hf, _H2(), _Hash(), __eql,
kono
parents:
diff changeset
446 __key_extract(), __a)
kono
parents:
diff changeset
447 { }
kono
parents:
diff changeset
448
kono
parents:
diff changeset
449 template<typename _InputIterator>
kono
parents:
diff changeset
450 _Hashtable(_InputIterator __f, _InputIterator __l,
kono
parents:
diff changeset
451 size_type __n = 0,
kono
parents:
diff changeset
452 const _H1& __hf = _H1(),
kono
parents:
diff changeset
453 const key_equal& __eql = key_equal(),
kono
parents:
diff changeset
454 const allocator_type& __a = allocator_type())
kono
parents:
diff changeset
455 : _Hashtable(__f, __l, __n, __hf, _H2(), _Hash(), __eql,
kono
parents:
diff changeset
456 __key_extract(), __a)
kono
parents:
diff changeset
457 { }
kono
parents:
diff changeset
458
kono
parents:
diff changeset
459 _Hashtable(initializer_list<value_type> __l,
kono
parents:
diff changeset
460 size_type __n = 0,
kono
parents:
diff changeset
461 const _H1& __hf = _H1(),
kono
parents:
diff changeset
462 const key_equal& __eql = key_equal(),
kono
parents:
diff changeset
463 const allocator_type& __a = allocator_type())
kono
parents:
diff changeset
464 : _Hashtable(__l.begin(), __l.end(), __n, __hf, _H2(), _Hash(), __eql,
kono
parents:
diff changeset
465 __key_extract(), __a)
kono
parents:
diff changeset
466 { }
kono
parents:
diff changeset
467
kono
parents:
diff changeset
468 _Hashtable&
kono
parents:
diff changeset
469 operator=(const _Hashtable& __ht);
kono
parents:
diff changeset
470
kono
parents:
diff changeset
471 _Hashtable&
kono
parents:
diff changeset
472 operator=(_Hashtable&& __ht)
kono
parents:
diff changeset
473 noexcept(__node_alloc_traits::_S_nothrow_move()
kono
parents:
diff changeset
474 && is_nothrow_move_assignable<_H1>::value
kono
parents:
diff changeset
475 && is_nothrow_move_assignable<_Equal>::value)
kono
parents:
diff changeset
476 {
kono
parents:
diff changeset
477 constexpr bool __move_storage =
kono
parents:
diff changeset
478 __node_alloc_traits::_S_propagate_on_move_assign()
kono
parents:
diff changeset
479 || __node_alloc_traits::_S_always_equal();
kono
parents:
diff changeset
480 _M_move_assign(std::move(__ht), __bool_constant<__move_storage>());
kono
parents:
diff changeset
481 return *this;
kono
parents:
diff changeset
482 }
kono
parents:
diff changeset
483
kono
parents:
diff changeset
484 _Hashtable&
kono
parents:
diff changeset
485 operator=(initializer_list<value_type> __l)
kono
parents:
diff changeset
486 {
kono
parents:
diff changeset
487 __reuse_or_alloc_node_type __roan(_M_begin(), *this);
kono
parents:
diff changeset
488 _M_before_begin._M_nxt = nullptr;
kono
parents:
diff changeset
489 clear();
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
490 this->_M_insert_range(__l.begin(), __l.end(), __roan, __unique_keys());
111
kono
parents:
diff changeset
491 return *this;
kono
parents:
diff changeset
492 }
kono
parents:
diff changeset
493
kono
parents:
diff changeset
494 ~_Hashtable() noexcept;
kono
parents:
diff changeset
495
kono
parents:
diff changeset
496 void
kono
parents:
diff changeset
497 swap(_Hashtable&)
kono
parents:
diff changeset
498 noexcept(__and_<__is_nothrow_swappable<_H1>,
kono
parents:
diff changeset
499 __is_nothrow_swappable<_Equal>>::value);
kono
parents:
diff changeset
500
kono
parents:
diff changeset
501 // Basic container operations
kono
parents:
diff changeset
502 iterator
kono
parents:
diff changeset
503 begin() noexcept
kono
parents:
diff changeset
504 { return iterator(_M_begin()); }
kono
parents:
diff changeset
505
kono
parents:
diff changeset
506 const_iterator
kono
parents:
diff changeset
507 begin() const noexcept
kono
parents:
diff changeset
508 { return const_iterator(_M_begin()); }
kono
parents:
diff changeset
509
kono
parents:
diff changeset
510 iterator
kono
parents:
diff changeset
511 end() noexcept
kono
parents:
diff changeset
512 { return iterator(nullptr); }
kono
parents:
diff changeset
513
kono
parents:
diff changeset
514 const_iterator
kono
parents:
diff changeset
515 end() const noexcept
kono
parents:
diff changeset
516 { return const_iterator(nullptr); }
kono
parents:
diff changeset
517
kono
parents:
diff changeset
518 const_iterator
kono
parents:
diff changeset
519 cbegin() const noexcept
kono
parents:
diff changeset
520 { return const_iterator(_M_begin()); }
kono
parents:
diff changeset
521
kono
parents:
diff changeset
522 const_iterator
kono
parents:
diff changeset
523 cend() const noexcept
kono
parents:
diff changeset
524 { return const_iterator(nullptr); }
kono
parents:
diff changeset
525
kono
parents:
diff changeset
526 size_type
kono
parents:
diff changeset
527 size() const noexcept
kono
parents:
diff changeset
528 { return _M_element_count; }
kono
parents:
diff changeset
529
kono
parents:
diff changeset
530 bool
kono
parents:
diff changeset
531 empty() const noexcept
kono
parents:
diff changeset
532 { return size() == 0; }
kono
parents:
diff changeset
533
kono
parents:
diff changeset
534 allocator_type
kono
parents:
diff changeset
535 get_allocator() const noexcept
kono
parents:
diff changeset
536 { return allocator_type(this->_M_node_allocator()); }
kono
parents:
diff changeset
537
kono
parents:
diff changeset
538 size_type
kono
parents:
diff changeset
539 max_size() const noexcept
kono
parents:
diff changeset
540 { return __node_alloc_traits::max_size(this->_M_node_allocator()); }
kono
parents:
diff changeset
541
kono
parents:
diff changeset
542 // Observers
kono
parents:
diff changeset
543 key_equal
kono
parents:
diff changeset
544 key_eq() const
kono
parents:
diff changeset
545 { return this->_M_eq(); }
kono
parents:
diff changeset
546
kono
parents:
diff changeset
547 // hash_function, if present, comes from _Hash_code_base.
kono
parents:
diff changeset
548
kono
parents:
diff changeset
549 // Bucket operations
kono
parents:
diff changeset
550 size_type
kono
parents:
diff changeset
551 bucket_count() const noexcept
kono
parents:
diff changeset
552 { return _M_bucket_count; }
kono
parents:
diff changeset
553
kono
parents:
diff changeset
554 size_type
kono
parents:
diff changeset
555 max_bucket_count() const noexcept
kono
parents:
diff changeset
556 { return max_size(); }
kono
parents:
diff changeset
557
kono
parents:
diff changeset
558 size_type
kono
parents:
diff changeset
559 bucket_size(size_type __n) const
kono
parents:
diff changeset
560 { return std::distance(begin(__n), end(__n)); }
kono
parents:
diff changeset
561
kono
parents:
diff changeset
562 size_type
kono
parents:
diff changeset
563 bucket(const key_type& __k) const
kono
parents:
diff changeset
564 { return _M_bucket_index(__k, this->_M_hash_code(__k)); }
kono
parents:
diff changeset
565
kono
parents:
diff changeset
566 local_iterator
kono
parents:
diff changeset
567 begin(size_type __n)
kono
parents:
diff changeset
568 {
kono
parents:
diff changeset
569 return local_iterator(*this, _M_bucket_begin(__n),
kono
parents:
diff changeset
570 __n, _M_bucket_count);
kono
parents:
diff changeset
571 }
kono
parents:
diff changeset
572
kono
parents:
diff changeset
573 local_iterator
kono
parents:
diff changeset
574 end(size_type __n)
kono
parents:
diff changeset
575 { return local_iterator(*this, nullptr, __n, _M_bucket_count); }
kono
parents:
diff changeset
576
kono
parents:
diff changeset
577 const_local_iterator
kono
parents:
diff changeset
578 begin(size_type __n) const
kono
parents:
diff changeset
579 {
kono
parents:
diff changeset
580 return const_local_iterator(*this, _M_bucket_begin(__n),
kono
parents:
diff changeset
581 __n, _M_bucket_count);
kono
parents:
diff changeset
582 }
kono
parents:
diff changeset
583
kono
parents:
diff changeset
584 const_local_iterator
kono
parents:
diff changeset
585 end(size_type __n) const
kono
parents:
diff changeset
586 { return const_local_iterator(*this, nullptr, __n, _M_bucket_count); }
kono
parents:
diff changeset
587
kono
parents:
diff changeset
588 // DR 691.
kono
parents:
diff changeset
589 const_local_iterator
kono
parents:
diff changeset
590 cbegin(size_type __n) const
kono
parents:
diff changeset
591 {
kono
parents:
diff changeset
592 return const_local_iterator(*this, _M_bucket_begin(__n),
kono
parents:
diff changeset
593 __n, _M_bucket_count);
kono
parents:
diff changeset
594 }
kono
parents:
diff changeset
595
kono
parents:
diff changeset
596 const_local_iterator
kono
parents:
diff changeset
597 cend(size_type __n) const
kono
parents:
diff changeset
598 { return const_local_iterator(*this, nullptr, __n, _M_bucket_count); }
kono
parents:
diff changeset
599
kono
parents:
diff changeset
600 float
kono
parents:
diff changeset
601 load_factor() const noexcept
kono
parents:
diff changeset
602 {
kono
parents:
diff changeset
603 return static_cast<float>(size()) / static_cast<float>(bucket_count());
kono
parents:
diff changeset
604 }
kono
parents:
diff changeset
605
kono
parents:
diff changeset
606 // max_load_factor, if present, comes from _Rehash_base.
kono
parents:
diff changeset
607
kono
parents:
diff changeset
608 // Generalization of max_load_factor. Extension, not found in
kono
parents:
diff changeset
609 // TR1. Only useful if _RehashPolicy is something other than
kono
parents:
diff changeset
610 // the default.
kono
parents:
diff changeset
611 const _RehashPolicy&
kono
parents:
diff changeset
612 __rehash_policy() const
kono
parents:
diff changeset
613 { return _M_rehash_policy; }
kono
parents:
diff changeset
614
kono
parents:
diff changeset
615 void
kono
parents:
diff changeset
616 __rehash_policy(const _RehashPolicy& __pol)
kono
parents:
diff changeset
617 { _M_rehash_policy = __pol; }
kono
parents:
diff changeset
618
kono
parents:
diff changeset
619 // Lookup.
kono
parents:
diff changeset
620 iterator
kono
parents:
diff changeset
621 find(const key_type& __k);
kono
parents:
diff changeset
622
kono
parents:
diff changeset
623 const_iterator
kono
parents:
diff changeset
624 find(const key_type& __k) const;
kono
parents:
diff changeset
625
kono
parents:
diff changeset
626 size_type
kono
parents:
diff changeset
627 count(const key_type& __k) const;
kono
parents:
diff changeset
628
kono
parents:
diff changeset
629 std::pair<iterator, iterator>
kono
parents:
diff changeset
630 equal_range(const key_type& __k);
kono
parents:
diff changeset
631
kono
parents:
diff changeset
632 std::pair<const_iterator, const_iterator>
kono
parents:
diff changeset
633 equal_range(const key_type& __k) const;
kono
parents:
diff changeset
634
kono
parents:
diff changeset
635 protected:
kono
parents:
diff changeset
636 // Bucket index computation helpers.
kono
parents:
diff changeset
637 size_type
kono
parents:
diff changeset
638 _M_bucket_index(__node_type* __n) const noexcept
kono
parents:
diff changeset
639 { return __hash_code_base::_M_bucket_index(__n, _M_bucket_count); }
kono
parents:
diff changeset
640
kono
parents:
diff changeset
641 size_type
kono
parents:
diff changeset
642 _M_bucket_index(const key_type& __k, __hash_code __c) const
kono
parents:
diff changeset
643 { return __hash_code_base::_M_bucket_index(__k, __c, _M_bucket_count); }
kono
parents:
diff changeset
644
kono
parents:
diff changeset
645 // Find and insert helper functions and types
kono
parents:
diff changeset
646 // Find the node before the one matching the criteria.
kono
parents:
diff changeset
647 __node_base*
kono
parents:
diff changeset
648 _M_find_before_node(size_type, const key_type&, __hash_code) const;
kono
parents:
diff changeset
649
kono
parents:
diff changeset
650 __node_type*
kono
parents:
diff changeset
651 _M_find_node(size_type __bkt, const key_type& __key,
kono
parents:
diff changeset
652 __hash_code __c) const
kono
parents:
diff changeset
653 {
kono
parents:
diff changeset
654 __node_base* __before_n = _M_find_before_node(__bkt, __key, __c);
kono
parents:
diff changeset
655 if (__before_n)
kono
parents:
diff changeset
656 return static_cast<__node_type*>(__before_n->_M_nxt);
kono
parents:
diff changeset
657 return nullptr;
kono
parents:
diff changeset
658 }
kono
parents:
diff changeset
659
kono
parents:
diff changeset
660 // Insert a node at the beginning of a bucket.
kono
parents:
diff changeset
661 void
kono
parents:
diff changeset
662 _M_insert_bucket_begin(size_type, __node_type*);
kono
parents:
diff changeset
663
kono
parents:
diff changeset
664 // Remove the bucket first node
kono
parents:
diff changeset
665 void
kono
parents:
diff changeset
666 _M_remove_bucket_begin(size_type __bkt, __node_type* __next_n,
kono
parents:
diff changeset
667 size_type __next_bkt);
kono
parents:
diff changeset
668
kono
parents:
diff changeset
669 // Get the node before __n in the bucket __bkt
kono
parents:
diff changeset
670 __node_base*
kono
parents:
diff changeset
671 _M_get_previous_node(size_type __bkt, __node_base* __n);
kono
parents:
diff changeset
672
kono
parents:
diff changeset
673 // Insert node with hash code __code, in bucket bkt if no rehash (assumes
kono
parents:
diff changeset
674 // no element with its key already present). Take ownership of the node,
kono
parents:
diff changeset
675 // deallocate it on exception.
kono
parents:
diff changeset
676 iterator
kono
parents:
diff changeset
677 _M_insert_unique_node(size_type __bkt, __hash_code __code,
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
678 __node_type* __n, size_type __n_elt = 1);
111
kono
parents:
diff changeset
679
kono
parents:
diff changeset
680 // Insert node with hash code __code. Take ownership of the node,
kono
parents:
diff changeset
681 // deallocate it on exception.
kono
parents:
diff changeset
682 iterator
kono
parents:
diff changeset
683 _M_insert_multi_node(__node_type* __hint,
kono
parents:
diff changeset
684 __hash_code __code, __node_type* __n);
kono
parents:
diff changeset
685
kono
parents:
diff changeset
686 template<typename... _Args>
kono
parents:
diff changeset
687 std::pair<iterator, bool>
kono
parents:
diff changeset
688 _M_emplace(std::true_type, _Args&&... __args);
kono
parents:
diff changeset
689
kono
parents:
diff changeset
690 template<typename... _Args>
kono
parents:
diff changeset
691 iterator
kono
parents:
diff changeset
692 _M_emplace(std::false_type __uk, _Args&&... __args)
kono
parents:
diff changeset
693 { return _M_emplace(cend(), __uk, std::forward<_Args>(__args)...); }
kono
parents:
diff changeset
694
kono
parents:
diff changeset
695 // Emplace with hint, useless when keys are unique.
kono
parents:
diff changeset
696 template<typename... _Args>
kono
parents:
diff changeset
697 iterator
kono
parents:
diff changeset
698 _M_emplace(const_iterator, std::true_type __uk, _Args&&... __args)
kono
parents:
diff changeset
699 { return _M_emplace(__uk, std::forward<_Args>(__args)...).first; }
kono
parents:
diff changeset
700
kono
parents:
diff changeset
701 template<typename... _Args>
kono
parents:
diff changeset
702 iterator
kono
parents:
diff changeset
703 _M_emplace(const_iterator, std::false_type, _Args&&... __args);
kono
parents:
diff changeset
704
kono
parents:
diff changeset
705 template<typename _Arg, typename _NodeGenerator>
kono
parents:
diff changeset
706 std::pair<iterator, bool>
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
707 _M_insert(_Arg&&, const _NodeGenerator&, true_type, size_type = 1);
111
kono
parents:
diff changeset
708
kono
parents:
diff changeset
709 template<typename _Arg, typename _NodeGenerator>
kono
parents:
diff changeset
710 iterator
kono
parents:
diff changeset
711 _M_insert(_Arg&& __arg, const _NodeGenerator& __node_gen,
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
712 false_type __uk)
111
kono
parents:
diff changeset
713 {
kono
parents:
diff changeset
714 return _M_insert(cend(), std::forward<_Arg>(__arg), __node_gen,
kono
parents:
diff changeset
715 __uk);
kono
parents:
diff changeset
716 }
kono
parents:
diff changeset
717
kono
parents:
diff changeset
718 // Insert with hint, not used when keys are unique.
kono
parents:
diff changeset
719 template<typename _Arg, typename _NodeGenerator>
kono
parents:
diff changeset
720 iterator
kono
parents:
diff changeset
721 _M_insert(const_iterator, _Arg&& __arg,
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
722 const _NodeGenerator& __node_gen, true_type __uk)
111
kono
parents:
diff changeset
723 {
kono
parents:
diff changeset
724 return
kono
parents:
diff changeset
725 _M_insert(std::forward<_Arg>(__arg), __node_gen, __uk).first;
kono
parents:
diff changeset
726 }
kono
parents:
diff changeset
727
kono
parents:
diff changeset
728 // Insert with hint when keys are not unique.
kono
parents:
diff changeset
729 template<typename _Arg, typename _NodeGenerator>
kono
parents:
diff changeset
730 iterator
kono
parents:
diff changeset
731 _M_insert(const_iterator, _Arg&&,
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
732 const _NodeGenerator&, false_type);
111
kono
parents:
diff changeset
733
kono
parents:
diff changeset
734 size_type
kono
parents:
diff changeset
735 _M_erase(std::true_type, const key_type&);
kono
parents:
diff changeset
736
kono
parents:
diff changeset
737 size_type
kono
parents:
diff changeset
738 _M_erase(std::false_type, const key_type&);
kono
parents:
diff changeset
739
kono
parents:
diff changeset
740 iterator
kono
parents:
diff changeset
741 _M_erase(size_type __bkt, __node_base* __prev_n, __node_type* __n);
kono
parents:
diff changeset
742
kono
parents:
diff changeset
743 public:
kono
parents:
diff changeset
744 // Emplace
kono
parents:
diff changeset
745 template<typename... _Args>
kono
parents:
diff changeset
746 __ireturn_type
kono
parents:
diff changeset
747 emplace(_Args&&... __args)
kono
parents:
diff changeset
748 { return _M_emplace(__unique_keys(), std::forward<_Args>(__args)...); }
kono
parents:
diff changeset
749
kono
parents:
diff changeset
750 template<typename... _Args>
kono
parents:
diff changeset
751 iterator
kono
parents:
diff changeset
752 emplace_hint(const_iterator __hint, _Args&&... __args)
kono
parents:
diff changeset
753 {
kono
parents:
diff changeset
754 return _M_emplace(__hint, __unique_keys(),
kono
parents:
diff changeset
755 std::forward<_Args>(__args)...);
kono
parents:
diff changeset
756 }
kono
parents:
diff changeset
757
kono
parents:
diff changeset
758 // Insert member functions via inheritance.
kono
parents:
diff changeset
759
kono
parents:
diff changeset
760 // Erase
kono
parents:
diff changeset
761 iterator
kono
parents:
diff changeset
762 erase(const_iterator);
kono
parents:
diff changeset
763
kono
parents:
diff changeset
764 // LWG 2059.
kono
parents:
diff changeset
765 iterator
kono
parents:
diff changeset
766 erase(iterator __it)
kono
parents:
diff changeset
767 { return erase(const_iterator(__it)); }
kono
parents:
diff changeset
768
kono
parents:
diff changeset
769 size_type
kono
parents:
diff changeset
770 erase(const key_type& __k)
kono
parents:
diff changeset
771 { return _M_erase(__unique_keys(), __k); }
kono
parents:
diff changeset
772
kono
parents:
diff changeset
773 iterator
kono
parents:
diff changeset
774 erase(const_iterator, const_iterator);
kono
parents:
diff changeset
775
kono
parents:
diff changeset
776 void
kono
parents:
diff changeset
777 clear() noexcept;
kono
parents:
diff changeset
778
kono
parents:
diff changeset
779 // Set number of buckets to be appropriate for container of n element.
kono
parents:
diff changeset
780 void rehash(size_type __n);
kono
parents:
diff changeset
781
kono
parents:
diff changeset
782 // DR 1189.
kono
parents:
diff changeset
783 // reserve, if present, comes from _Rehash_base.
kono
parents:
diff changeset
784
kono
parents:
diff changeset
785 #if __cplusplus > 201402L
kono
parents:
diff changeset
786 /// Re-insert an extracted node into a container with unique keys.
kono
parents:
diff changeset
787 insert_return_type
kono
parents:
diff changeset
788 _M_reinsert_node(node_type&& __nh)
kono
parents:
diff changeset
789 {
kono
parents:
diff changeset
790 insert_return_type __ret;
kono
parents:
diff changeset
791 if (__nh.empty())
kono
parents:
diff changeset
792 __ret.position = end();
kono
parents:
diff changeset
793 else
kono
parents:
diff changeset
794 {
kono
parents:
diff changeset
795 __glibcxx_assert(get_allocator() == __nh.get_allocator());
kono
parents:
diff changeset
796
kono
parents:
diff changeset
797 const key_type& __k = __nh._M_key();
kono
parents:
diff changeset
798 __hash_code __code = this->_M_hash_code(__k);
kono
parents:
diff changeset
799 size_type __bkt = _M_bucket_index(__k, __code);
kono
parents:
diff changeset
800 if (__node_type* __n = _M_find_node(__bkt, __k, __code))
kono
parents:
diff changeset
801 {
kono
parents:
diff changeset
802 __ret.node = std::move(__nh);
kono
parents:
diff changeset
803 __ret.position = iterator(__n);
kono
parents:
diff changeset
804 __ret.inserted = false;
kono
parents:
diff changeset
805 }
kono
parents:
diff changeset
806 else
kono
parents:
diff changeset
807 {
kono
parents:
diff changeset
808 __ret.position
kono
parents:
diff changeset
809 = _M_insert_unique_node(__bkt, __code, __nh._M_ptr);
kono
parents:
diff changeset
810 __nh._M_ptr = nullptr;
kono
parents:
diff changeset
811 __ret.inserted = true;
kono
parents:
diff changeset
812 }
kono
parents:
diff changeset
813 }
kono
parents:
diff changeset
814 return __ret;
kono
parents:
diff changeset
815 }
kono
parents:
diff changeset
816
kono
parents:
diff changeset
817 /// Re-insert an extracted node into a container with equivalent keys.
kono
parents:
diff changeset
818 iterator
kono
parents:
diff changeset
819 _M_reinsert_node_multi(const_iterator __hint, node_type&& __nh)
kono
parents:
diff changeset
820 {
kono
parents:
diff changeset
821 iterator __ret;
kono
parents:
diff changeset
822 if (__nh.empty())
kono
parents:
diff changeset
823 __ret = end();
kono
parents:
diff changeset
824 else
kono
parents:
diff changeset
825 {
kono
parents:
diff changeset
826 __glibcxx_assert(get_allocator() == __nh.get_allocator());
kono
parents:
diff changeset
827
kono
parents:
diff changeset
828 auto __code = this->_M_hash_code(__nh._M_key());
kono
parents:
diff changeset
829 auto __node = std::exchange(__nh._M_ptr, nullptr);
kono
parents:
diff changeset
830 // FIXME: this deallocates the node on exception.
kono
parents:
diff changeset
831 __ret = _M_insert_multi_node(__hint._M_cur, __code, __node);
kono
parents:
diff changeset
832 }
kono
parents:
diff changeset
833 return __ret;
kono
parents:
diff changeset
834 }
kono
parents:
diff changeset
835
kono
parents:
diff changeset
836 /// Extract a node.
kono
parents:
diff changeset
837 node_type
kono
parents:
diff changeset
838 extract(const_iterator __pos)
kono
parents:
diff changeset
839 {
kono
parents:
diff changeset
840 __node_type* __n = __pos._M_cur;
kono
parents:
diff changeset
841 size_t __bkt = _M_bucket_index(__n);
kono
parents:
diff changeset
842
kono
parents:
diff changeset
843 // Look for previous node to unlink it from the erased one, this
kono
parents:
diff changeset
844 // is why we need buckets to contain the before begin to make
kono
parents:
diff changeset
845 // this search fast.
kono
parents:
diff changeset
846 __node_base* __prev_n = _M_get_previous_node(__bkt, __n);
kono
parents:
diff changeset
847
kono
parents:
diff changeset
848 if (__prev_n == _M_buckets[__bkt])
kono
parents:
diff changeset
849 _M_remove_bucket_begin(__bkt, __n->_M_next(),
kono
parents:
diff changeset
850 __n->_M_nxt ? _M_bucket_index(__n->_M_next()) : 0);
kono
parents:
diff changeset
851 else if (__n->_M_nxt)
kono
parents:
diff changeset
852 {
kono
parents:
diff changeset
853 size_type __next_bkt = _M_bucket_index(__n->_M_next());
kono
parents:
diff changeset
854 if (__next_bkt != __bkt)
kono
parents:
diff changeset
855 _M_buckets[__next_bkt] = __prev_n;
kono
parents:
diff changeset
856 }
kono
parents:
diff changeset
857
kono
parents:
diff changeset
858 __prev_n->_M_nxt = __n->_M_nxt;
kono
parents:
diff changeset
859 __n->_M_nxt = nullptr;
kono
parents:
diff changeset
860 --_M_element_count;
kono
parents:
diff changeset
861 return { __n, this->_M_node_allocator() };
kono
parents:
diff changeset
862 }
kono
parents:
diff changeset
863
kono
parents:
diff changeset
864 /// Extract a node.
kono
parents:
diff changeset
865 node_type
kono
parents:
diff changeset
866 extract(const _Key& __k)
kono
parents:
diff changeset
867 {
kono
parents:
diff changeset
868 node_type __nh;
kono
parents:
diff changeset
869 auto __pos = find(__k);
kono
parents:
diff changeset
870 if (__pos != end())
kono
parents:
diff changeset
871 __nh = extract(const_iterator(__pos));
kono
parents:
diff changeset
872 return __nh;
kono
parents:
diff changeset
873 }
kono
parents:
diff changeset
874
kono
parents:
diff changeset
875 /// Merge from a compatible container into one with unique keys.
kono
parents:
diff changeset
876 template<typename _Compatible_Hashtable>
kono
parents:
diff changeset
877 void
kono
parents:
diff changeset
878 _M_merge_unique(_Compatible_Hashtable& __src) noexcept
kono
parents:
diff changeset
879 {
kono
parents:
diff changeset
880 static_assert(is_same_v<typename _Compatible_Hashtable::node_type,
kono
parents:
diff changeset
881 node_type>, "Node types are compatible");
kono
parents:
diff changeset
882 __glibcxx_assert(get_allocator() == __src.get_allocator());
kono
parents:
diff changeset
883
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
884 auto __n_elt = __src.size();
111
kono
parents:
diff changeset
885 for (auto __i = __src.begin(), __end = __src.end(); __i != __end;)
kono
parents:
diff changeset
886 {
kono
parents:
diff changeset
887 auto __pos = __i++;
kono
parents:
diff changeset
888 const key_type& __k = this->_M_extract()(__pos._M_cur->_M_v());
kono
parents:
diff changeset
889 __hash_code __code = this->_M_hash_code(__k);
kono
parents:
diff changeset
890 size_type __bkt = _M_bucket_index(__k, __code);
kono
parents:
diff changeset
891 if (_M_find_node(__bkt, __k, __code) == nullptr)
kono
parents:
diff changeset
892 {
kono
parents:
diff changeset
893 auto __nh = __src.extract(__pos);
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
894 _M_insert_unique_node(__bkt, __code, __nh._M_ptr, __n_elt);
111
kono
parents:
diff changeset
895 __nh._M_ptr = nullptr;
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
896 __n_elt = 1;
111
kono
parents:
diff changeset
897 }
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
898 else if (__n_elt != 1)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
899 --__n_elt;
111
kono
parents:
diff changeset
900 }
kono
parents:
diff changeset
901 }
kono
parents:
diff changeset
902
kono
parents:
diff changeset
903 /// Merge from a compatible container into one with equivalent keys.
kono
parents:
diff changeset
904 template<typename _Compatible_Hashtable>
kono
parents:
diff changeset
905 void
kono
parents:
diff changeset
906 _M_merge_multi(_Compatible_Hashtable& __src) noexcept
kono
parents:
diff changeset
907 {
kono
parents:
diff changeset
908 static_assert(is_same_v<typename _Compatible_Hashtable::node_type,
kono
parents:
diff changeset
909 node_type>, "Node types are compatible");
kono
parents:
diff changeset
910 __glibcxx_assert(get_allocator() == __src.get_allocator());
kono
parents:
diff changeset
911
kono
parents:
diff changeset
912 this->reserve(size() + __src.size());
kono
parents:
diff changeset
913 for (auto __i = __src.begin(), __end = __src.end(); __i != __end;)
kono
parents:
diff changeset
914 _M_reinsert_node_multi(cend(), __src.extract(__i++));
kono
parents:
diff changeset
915 }
kono
parents:
diff changeset
916 #endif // C++17
kono
parents:
diff changeset
917
kono
parents:
diff changeset
918 private:
kono
parents:
diff changeset
919 // Helper rehash method used when keys are unique.
kono
parents:
diff changeset
920 void _M_rehash_aux(size_type __n, std::true_type);
kono
parents:
diff changeset
921
kono
parents:
diff changeset
922 // Helper rehash method used when keys can be non-unique.
kono
parents:
diff changeset
923 void _M_rehash_aux(size_type __n, std::false_type);
kono
parents:
diff changeset
924
kono
parents:
diff changeset
925 // Unconditionally change size of bucket array to n, restore
kono
parents:
diff changeset
926 // hash policy state to __state on exception.
kono
parents:
diff changeset
927 void _M_rehash(size_type __n, const __rehash_state& __state);
kono
parents:
diff changeset
928 };
kono
parents:
diff changeset
929
kono
parents:
diff changeset
930
kono
parents:
diff changeset
931 // Definitions of class template _Hashtable's out-of-line member functions.
kono
parents:
diff changeset
932 template<typename _Key, typename _Value,
kono
parents:
diff changeset
933 typename _Alloc, typename _ExtractKey, typename _Equal,
kono
parents:
diff changeset
934 typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
kono
parents:
diff changeset
935 typename _Traits>
kono
parents:
diff changeset
936 auto
kono
parents:
diff changeset
937 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
kono
parents:
diff changeset
938 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
kono
parents:
diff changeset
939 _M_bucket_begin(size_type __bkt) const
kono
parents:
diff changeset
940 -> __node_type*
kono
parents:
diff changeset
941 {
kono
parents:
diff changeset
942 __node_base* __n = _M_buckets[__bkt];
kono
parents:
diff changeset
943 return __n ? static_cast<__node_type*>(__n->_M_nxt) : nullptr;
kono
parents:
diff changeset
944 }
kono
parents:
diff changeset
945
kono
parents:
diff changeset
946 template<typename _Key, typename _Value,
kono
parents:
diff changeset
947 typename _Alloc, typename _ExtractKey, typename _Equal,
kono
parents:
diff changeset
948 typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
kono
parents:
diff changeset
949 typename _Traits>
kono
parents:
diff changeset
950 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
kono
parents:
diff changeset
951 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
kono
parents:
diff changeset
952 _Hashtable(size_type __bucket_hint,
kono
parents:
diff changeset
953 const _H1& __h1, const _H2& __h2, const _Hash& __h,
kono
parents:
diff changeset
954 const _Equal& __eq, const _ExtractKey& __exk,
kono
parents:
diff changeset
955 const allocator_type& __a)
kono
parents:
diff changeset
956 : _Hashtable(__h1, __h2, __h, __eq, __exk, __a)
kono
parents:
diff changeset
957 {
kono
parents:
diff changeset
958 auto __bkt = _M_rehash_policy._M_next_bkt(__bucket_hint);
kono
parents:
diff changeset
959 if (__bkt > _M_bucket_count)
kono
parents:
diff changeset
960 {
kono
parents:
diff changeset
961 _M_buckets = _M_allocate_buckets(__bkt);
kono
parents:
diff changeset
962 _M_bucket_count = __bkt;
kono
parents:
diff changeset
963 }
kono
parents:
diff changeset
964 }
kono
parents:
diff changeset
965
kono
parents:
diff changeset
966 template<typename _Key, typename _Value,
kono
parents:
diff changeset
967 typename _Alloc, typename _ExtractKey, typename _Equal,
kono
parents:
diff changeset
968 typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
kono
parents:
diff changeset
969 typename _Traits>
kono
parents:
diff changeset
970 template<typename _InputIterator>
kono
parents:
diff changeset
971 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
kono
parents:
diff changeset
972 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
kono
parents:
diff changeset
973 _Hashtable(_InputIterator __f, _InputIterator __l,
kono
parents:
diff changeset
974 size_type __bucket_hint,
kono
parents:
diff changeset
975 const _H1& __h1, const _H2& __h2, const _Hash& __h,
kono
parents:
diff changeset
976 const _Equal& __eq, const _ExtractKey& __exk,
kono
parents:
diff changeset
977 const allocator_type& __a)
kono
parents:
diff changeset
978 : _Hashtable(__h1, __h2, __h, __eq, __exk, __a)
kono
parents:
diff changeset
979 {
kono
parents:
diff changeset
980 auto __nb_elems = __detail::__distance_fw(__f, __l);
kono
parents:
diff changeset
981 auto __bkt_count =
kono
parents:
diff changeset
982 _M_rehash_policy._M_next_bkt(
kono
parents:
diff changeset
983 std::max(_M_rehash_policy._M_bkt_for_elements(__nb_elems),
kono
parents:
diff changeset
984 __bucket_hint));
kono
parents:
diff changeset
985
kono
parents:
diff changeset
986 if (__bkt_count > _M_bucket_count)
kono
parents:
diff changeset
987 {
kono
parents:
diff changeset
988 _M_buckets = _M_allocate_buckets(__bkt_count);
kono
parents:
diff changeset
989 _M_bucket_count = __bkt_count;
kono
parents:
diff changeset
990 }
kono
parents:
diff changeset
991
kono
parents:
diff changeset
992 for (; __f != __l; ++__f)
kono
parents:
diff changeset
993 this->insert(*__f);
kono
parents:
diff changeset
994 }
kono
parents:
diff changeset
995
kono
parents:
diff changeset
996 template<typename _Key, typename _Value,
kono
parents:
diff changeset
997 typename _Alloc, typename _ExtractKey, typename _Equal,
kono
parents:
diff changeset
998 typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
kono
parents:
diff changeset
999 typename _Traits>
kono
parents:
diff changeset
1000 auto
kono
parents:
diff changeset
1001 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
kono
parents:
diff changeset
1002 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
kono
parents:
diff changeset
1003 operator=(const _Hashtable& __ht)
kono
parents:
diff changeset
1004 -> _Hashtable&
kono
parents:
diff changeset
1005 {
kono
parents:
diff changeset
1006 if (&__ht == this)
kono
parents:
diff changeset
1007 return *this;
kono
parents:
diff changeset
1008
kono
parents:
diff changeset
1009 if (__node_alloc_traits::_S_propagate_on_copy_assign())
kono
parents:
diff changeset
1010 {
kono
parents:
diff changeset
1011 auto& __this_alloc = this->_M_node_allocator();
kono
parents:
diff changeset
1012 auto& __that_alloc = __ht._M_node_allocator();
kono
parents:
diff changeset
1013 if (!__node_alloc_traits::_S_always_equal()
kono
parents:
diff changeset
1014 && __this_alloc != __that_alloc)
kono
parents:
diff changeset
1015 {
kono
parents:
diff changeset
1016 // Replacement allocator cannot free existing storage.
kono
parents:
diff changeset
1017 this->_M_deallocate_nodes(_M_begin());
kono
parents:
diff changeset
1018 _M_before_begin._M_nxt = nullptr;
kono
parents:
diff changeset
1019 _M_deallocate_buckets();
kono
parents:
diff changeset
1020 _M_buckets = nullptr;
kono
parents:
diff changeset
1021 std::__alloc_on_copy(__this_alloc, __that_alloc);
kono
parents:
diff changeset
1022 __hashtable_base::operator=(__ht);
kono
parents:
diff changeset
1023 _M_bucket_count = __ht._M_bucket_count;
kono
parents:
diff changeset
1024 _M_element_count = __ht._M_element_count;
kono
parents:
diff changeset
1025 _M_rehash_policy = __ht._M_rehash_policy;
kono
parents:
diff changeset
1026 __try
kono
parents:
diff changeset
1027 {
kono
parents:
diff changeset
1028 _M_assign(__ht,
kono
parents:
diff changeset
1029 [this](const __node_type* __n)
kono
parents:
diff changeset
1030 { return this->_M_allocate_node(__n->_M_v()); });
kono
parents:
diff changeset
1031 }
kono
parents:
diff changeset
1032 __catch(...)
kono
parents:
diff changeset
1033 {
kono
parents:
diff changeset
1034 // _M_assign took care of deallocating all memory. Now we
kono
parents:
diff changeset
1035 // must make sure this instance remains in a usable state.
kono
parents:
diff changeset
1036 _M_reset();
kono
parents:
diff changeset
1037 __throw_exception_again;
kono
parents:
diff changeset
1038 }
kono
parents:
diff changeset
1039 return *this;
kono
parents:
diff changeset
1040 }
kono
parents:
diff changeset
1041 std::__alloc_on_copy(__this_alloc, __that_alloc);
kono
parents:
diff changeset
1042 }
kono
parents:
diff changeset
1043
kono
parents:
diff changeset
1044 // Reuse allocated buckets and nodes.
kono
parents:
diff changeset
1045 __bucket_type* __former_buckets = nullptr;
kono
parents:
diff changeset
1046 std::size_t __former_bucket_count = _M_bucket_count;
kono
parents:
diff changeset
1047 const __rehash_state& __former_state = _M_rehash_policy._M_state();
kono
parents:
diff changeset
1048
kono
parents:
diff changeset
1049 if (_M_bucket_count != __ht._M_bucket_count)
kono
parents:
diff changeset
1050 {
kono
parents:
diff changeset
1051 __former_buckets = _M_buckets;
kono
parents:
diff changeset
1052 _M_buckets = _M_allocate_buckets(__ht._M_bucket_count);
kono
parents:
diff changeset
1053 _M_bucket_count = __ht._M_bucket_count;
kono
parents:
diff changeset
1054 }
kono
parents:
diff changeset
1055 else
kono
parents:
diff changeset
1056 __builtin_memset(_M_buckets, 0,
kono
parents:
diff changeset
1057 _M_bucket_count * sizeof(__bucket_type));
kono
parents:
diff changeset
1058
kono
parents:
diff changeset
1059 __try
kono
parents:
diff changeset
1060 {
kono
parents:
diff changeset
1061 __hashtable_base::operator=(__ht);
kono
parents:
diff changeset
1062 _M_element_count = __ht._M_element_count;
kono
parents:
diff changeset
1063 _M_rehash_policy = __ht._M_rehash_policy;
kono
parents:
diff changeset
1064 __reuse_or_alloc_node_type __roan(_M_begin(), *this);
kono
parents:
diff changeset
1065 _M_before_begin._M_nxt = nullptr;
kono
parents:
diff changeset
1066 _M_assign(__ht,
kono
parents:
diff changeset
1067 [&__roan](const __node_type* __n)
kono
parents:
diff changeset
1068 { return __roan(__n->_M_v()); });
kono
parents:
diff changeset
1069 if (__former_buckets)
kono
parents:
diff changeset
1070 _M_deallocate_buckets(__former_buckets, __former_bucket_count);
kono
parents:
diff changeset
1071 }
kono
parents:
diff changeset
1072 __catch(...)
kono
parents:
diff changeset
1073 {
kono
parents:
diff changeset
1074 if (__former_buckets)
kono
parents:
diff changeset
1075 {
kono
parents:
diff changeset
1076 // Restore previous buckets.
kono
parents:
diff changeset
1077 _M_deallocate_buckets();
kono
parents:
diff changeset
1078 _M_rehash_policy._M_reset(__former_state);
kono
parents:
diff changeset
1079 _M_buckets = __former_buckets;
kono
parents:
diff changeset
1080 _M_bucket_count = __former_bucket_count;
kono
parents:
diff changeset
1081 }
kono
parents:
diff changeset
1082 __builtin_memset(_M_buckets, 0,
kono
parents:
diff changeset
1083 _M_bucket_count * sizeof(__bucket_type));
kono
parents:
diff changeset
1084 __throw_exception_again;
kono
parents:
diff changeset
1085 }
kono
parents:
diff changeset
1086 return *this;
kono
parents:
diff changeset
1087 }
kono
parents:
diff changeset
1088
kono
parents:
diff changeset
1089 template<typename _Key, typename _Value,
kono
parents:
diff changeset
1090 typename _Alloc, typename _ExtractKey, typename _Equal,
kono
parents:
diff changeset
1091 typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
kono
parents:
diff changeset
1092 typename _Traits>
kono
parents:
diff changeset
1093 template<typename _NodeGenerator>
kono
parents:
diff changeset
1094 void
kono
parents:
diff changeset
1095 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
kono
parents:
diff changeset
1096 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
kono
parents:
diff changeset
1097 _M_assign(const _Hashtable& __ht, const _NodeGenerator& __node_gen)
kono
parents:
diff changeset
1098 {
kono
parents:
diff changeset
1099 __bucket_type* __buckets = nullptr;
kono
parents:
diff changeset
1100 if (!_M_buckets)
kono
parents:
diff changeset
1101 _M_buckets = __buckets = _M_allocate_buckets(_M_bucket_count);
kono
parents:
diff changeset
1102
kono
parents:
diff changeset
1103 __try
kono
parents:
diff changeset
1104 {
kono
parents:
diff changeset
1105 if (!__ht._M_before_begin._M_nxt)
kono
parents:
diff changeset
1106 return;
kono
parents:
diff changeset
1107
kono
parents:
diff changeset
1108 // First deal with the special first node pointed to by
kono
parents:
diff changeset
1109 // _M_before_begin.
kono
parents:
diff changeset
1110 __node_type* __ht_n = __ht._M_begin();
kono
parents:
diff changeset
1111 __node_type* __this_n = __node_gen(__ht_n);
kono
parents:
diff changeset
1112 this->_M_copy_code(__this_n, __ht_n);
kono
parents:
diff changeset
1113 _M_before_begin._M_nxt = __this_n;
kono
parents:
diff changeset
1114 _M_buckets[_M_bucket_index(__this_n)] = &_M_before_begin;
kono
parents:
diff changeset
1115
kono
parents:
diff changeset
1116 // Then deal with other nodes.
kono
parents:
diff changeset
1117 __node_base* __prev_n = __this_n;
kono
parents:
diff changeset
1118 for (__ht_n = __ht_n->_M_next(); __ht_n; __ht_n = __ht_n->_M_next())
kono
parents:
diff changeset
1119 {
kono
parents:
diff changeset
1120 __this_n = __node_gen(__ht_n);
kono
parents:
diff changeset
1121 __prev_n->_M_nxt = __this_n;
kono
parents:
diff changeset
1122 this->_M_copy_code(__this_n, __ht_n);
kono
parents:
diff changeset
1123 size_type __bkt = _M_bucket_index(__this_n);
kono
parents:
diff changeset
1124 if (!_M_buckets[__bkt])
kono
parents:
diff changeset
1125 _M_buckets[__bkt] = __prev_n;
kono
parents:
diff changeset
1126 __prev_n = __this_n;
kono
parents:
diff changeset
1127 }
kono
parents:
diff changeset
1128 }
kono
parents:
diff changeset
1129 __catch(...)
kono
parents:
diff changeset
1130 {
kono
parents:
diff changeset
1131 clear();
kono
parents:
diff changeset
1132 if (__buckets)
kono
parents:
diff changeset
1133 _M_deallocate_buckets();
kono
parents:
diff changeset
1134 __throw_exception_again;
kono
parents:
diff changeset
1135 }
kono
parents:
diff changeset
1136 }
kono
parents:
diff changeset
1137
kono
parents:
diff changeset
1138 template<typename _Key, typename _Value,
kono
parents:
diff changeset
1139 typename _Alloc, typename _ExtractKey, typename _Equal,
kono
parents:
diff changeset
1140 typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
kono
parents:
diff changeset
1141 typename _Traits>
kono
parents:
diff changeset
1142 void
kono
parents:
diff changeset
1143 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
kono
parents:
diff changeset
1144 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
kono
parents:
diff changeset
1145 _M_reset() noexcept
kono
parents:
diff changeset
1146 {
kono
parents:
diff changeset
1147 _M_rehash_policy._M_reset();
kono
parents:
diff changeset
1148 _M_bucket_count = 1;
kono
parents:
diff changeset
1149 _M_single_bucket = nullptr;
kono
parents:
diff changeset
1150 _M_buckets = &_M_single_bucket;
kono
parents:
diff changeset
1151 _M_before_begin._M_nxt = nullptr;
kono
parents:
diff changeset
1152 _M_element_count = 0;
kono
parents:
diff changeset
1153 }
kono
parents:
diff changeset
1154
kono
parents:
diff changeset
1155 template<typename _Key, typename _Value,
kono
parents:
diff changeset
1156 typename _Alloc, typename _ExtractKey, typename _Equal,
kono
parents:
diff changeset
1157 typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
kono
parents:
diff changeset
1158 typename _Traits>
kono
parents:
diff changeset
1159 void
kono
parents:
diff changeset
1160 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
kono
parents:
diff changeset
1161 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
kono
parents:
diff changeset
1162 _M_move_assign(_Hashtable&& __ht, std::true_type)
kono
parents:
diff changeset
1163 {
kono
parents:
diff changeset
1164 this->_M_deallocate_nodes(_M_begin());
kono
parents:
diff changeset
1165 _M_deallocate_buckets();
kono
parents:
diff changeset
1166 __hashtable_base::operator=(std::move(__ht));
kono
parents:
diff changeset
1167 _M_rehash_policy = __ht._M_rehash_policy;
kono
parents:
diff changeset
1168 if (!__ht._M_uses_single_bucket())
kono
parents:
diff changeset
1169 _M_buckets = __ht._M_buckets;
kono
parents:
diff changeset
1170 else
kono
parents:
diff changeset
1171 {
kono
parents:
diff changeset
1172 _M_buckets = &_M_single_bucket;
kono
parents:
diff changeset
1173 _M_single_bucket = __ht._M_single_bucket;
kono
parents:
diff changeset
1174 }
kono
parents:
diff changeset
1175 _M_bucket_count = __ht._M_bucket_count;
kono
parents:
diff changeset
1176 _M_before_begin._M_nxt = __ht._M_before_begin._M_nxt;
kono
parents:
diff changeset
1177 _M_element_count = __ht._M_element_count;
kono
parents:
diff changeset
1178 std::__alloc_on_move(this->_M_node_allocator(), __ht._M_node_allocator());
kono
parents:
diff changeset
1179
kono
parents:
diff changeset
1180 // Fix buckets containing the _M_before_begin pointers that can't be
kono
parents:
diff changeset
1181 // moved.
kono
parents:
diff changeset
1182 if (_M_begin())
kono
parents:
diff changeset
1183 _M_buckets[_M_bucket_index(_M_begin())] = &_M_before_begin;
kono
parents:
diff changeset
1184 __ht._M_reset();
kono
parents:
diff changeset
1185 }
kono
parents:
diff changeset
1186
kono
parents:
diff changeset
1187 template<typename _Key, typename _Value,
kono
parents:
diff changeset
1188 typename _Alloc, typename _ExtractKey, typename _Equal,
kono
parents:
diff changeset
1189 typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
kono
parents:
diff changeset
1190 typename _Traits>
kono
parents:
diff changeset
1191 void
kono
parents:
diff changeset
1192 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
kono
parents:
diff changeset
1193 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
kono
parents:
diff changeset
1194 _M_move_assign(_Hashtable&& __ht, std::false_type)
kono
parents:
diff changeset
1195 {
kono
parents:
diff changeset
1196 if (__ht._M_node_allocator() == this->_M_node_allocator())
kono
parents:
diff changeset
1197 _M_move_assign(std::move(__ht), std::true_type());
kono
parents:
diff changeset
1198 else
kono
parents:
diff changeset
1199 {
kono
parents:
diff changeset
1200 // Can't move memory, move elements then.
kono
parents:
diff changeset
1201 __bucket_type* __former_buckets = nullptr;
kono
parents:
diff changeset
1202 size_type __former_bucket_count = _M_bucket_count;
kono
parents:
diff changeset
1203 const __rehash_state& __former_state = _M_rehash_policy._M_state();
kono
parents:
diff changeset
1204
kono
parents:
diff changeset
1205 if (_M_bucket_count != __ht._M_bucket_count)
kono
parents:
diff changeset
1206 {
kono
parents:
diff changeset
1207 __former_buckets = _M_buckets;
kono
parents:
diff changeset
1208 _M_buckets = _M_allocate_buckets(__ht._M_bucket_count);
kono
parents:
diff changeset
1209 _M_bucket_count = __ht._M_bucket_count;
kono
parents:
diff changeset
1210 }
kono
parents:
diff changeset
1211 else
kono
parents:
diff changeset
1212 __builtin_memset(_M_buckets, 0,
kono
parents:
diff changeset
1213 _M_bucket_count * sizeof(__bucket_type));
kono
parents:
diff changeset
1214
kono
parents:
diff changeset
1215 __try
kono
parents:
diff changeset
1216 {
kono
parents:
diff changeset
1217 __hashtable_base::operator=(std::move(__ht));
kono
parents:
diff changeset
1218 _M_element_count = __ht._M_element_count;
kono
parents:
diff changeset
1219 _M_rehash_policy = __ht._M_rehash_policy;
kono
parents:
diff changeset
1220 __reuse_or_alloc_node_type __roan(_M_begin(), *this);
kono
parents:
diff changeset
1221 _M_before_begin._M_nxt = nullptr;
kono
parents:
diff changeset
1222 _M_assign(__ht,
kono
parents:
diff changeset
1223 [&__roan](__node_type* __n)
kono
parents:
diff changeset
1224 { return __roan(std::move_if_noexcept(__n->_M_v())); });
kono
parents:
diff changeset
1225 __ht.clear();
kono
parents:
diff changeset
1226 }
kono
parents:
diff changeset
1227 __catch(...)
kono
parents:
diff changeset
1228 {
kono
parents:
diff changeset
1229 if (__former_buckets)
kono
parents:
diff changeset
1230 {
kono
parents:
diff changeset
1231 _M_deallocate_buckets();
kono
parents:
diff changeset
1232 _M_rehash_policy._M_reset(__former_state);
kono
parents:
diff changeset
1233 _M_buckets = __former_buckets;
kono
parents:
diff changeset
1234 _M_bucket_count = __former_bucket_count;
kono
parents:
diff changeset
1235 }
kono
parents:
diff changeset
1236 __builtin_memset(_M_buckets, 0,
kono
parents:
diff changeset
1237 _M_bucket_count * sizeof(__bucket_type));
kono
parents:
diff changeset
1238 __throw_exception_again;
kono
parents:
diff changeset
1239 }
kono
parents:
diff changeset
1240 }
kono
parents:
diff changeset
1241 }
kono
parents:
diff changeset
1242
kono
parents:
diff changeset
1243 template<typename _Key, typename _Value,
kono
parents:
diff changeset
1244 typename _Alloc, typename _ExtractKey, typename _Equal,
kono
parents:
diff changeset
1245 typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
kono
parents:
diff changeset
1246 typename _Traits>
kono
parents:
diff changeset
1247 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
kono
parents:
diff changeset
1248 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
kono
parents:
diff changeset
1249 _Hashtable(const _Hashtable& __ht)
kono
parents:
diff changeset
1250 : __hashtable_base(__ht),
kono
parents:
diff changeset
1251 __map_base(__ht),
kono
parents:
diff changeset
1252 __rehash_base(__ht),
kono
parents:
diff changeset
1253 __hashtable_alloc(
kono
parents:
diff changeset
1254 __node_alloc_traits::_S_select_on_copy(__ht._M_node_allocator())),
kono
parents:
diff changeset
1255 _M_buckets(nullptr),
kono
parents:
diff changeset
1256 _M_bucket_count(__ht._M_bucket_count),
kono
parents:
diff changeset
1257 _M_element_count(__ht._M_element_count),
kono
parents:
diff changeset
1258 _M_rehash_policy(__ht._M_rehash_policy)
kono
parents:
diff changeset
1259 {
kono
parents:
diff changeset
1260 _M_assign(__ht,
kono
parents:
diff changeset
1261 [this](const __node_type* __n)
kono
parents:
diff changeset
1262 { return this->_M_allocate_node(__n->_M_v()); });
kono
parents:
diff changeset
1263 }
kono
parents:
diff changeset
1264
kono
parents:
diff changeset
1265 template<typename _Key, typename _Value,
kono
parents:
diff changeset
1266 typename _Alloc, typename _ExtractKey, typename _Equal,
kono
parents:
diff changeset
1267 typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
kono
parents:
diff changeset
1268 typename _Traits>
kono
parents:
diff changeset
1269 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
kono
parents:
diff changeset
1270 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
kono
parents:
diff changeset
1271 _Hashtable(_Hashtable&& __ht) noexcept
kono
parents:
diff changeset
1272 : __hashtable_base(__ht),
kono
parents:
diff changeset
1273 __map_base(__ht),
kono
parents:
diff changeset
1274 __rehash_base(__ht),
kono
parents:
diff changeset
1275 __hashtable_alloc(std::move(__ht._M_base_alloc())),
kono
parents:
diff changeset
1276 _M_buckets(__ht._M_buckets),
kono
parents:
diff changeset
1277 _M_bucket_count(__ht._M_bucket_count),
kono
parents:
diff changeset
1278 _M_before_begin(__ht._M_before_begin._M_nxt),
kono
parents:
diff changeset
1279 _M_element_count(__ht._M_element_count),
kono
parents:
diff changeset
1280 _M_rehash_policy(__ht._M_rehash_policy)
kono
parents:
diff changeset
1281 {
kono
parents:
diff changeset
1282 // Update, if necessary, buckets if __ht is using its single bucket.
kono
parents:
diff changeset
1283 if (__ht._M_uses_single_bucket())
kono
parents:
diff changeset
1284 {
kono
parents:
diff changeset
1285 _M_buckets = &_M_single_bucket;
kono
parents:
diff changeset
1286 _M_single_bucket = __ht._M_single_bucket;
kono
parents:
diff changeset
1287 }
kono
parents:
diff changeset
1288
kono
parents:
diff changeset
1289 // Update, if necessary, bucket pointing to before begin that hasn't
kono
parents:
diff changeset
1290 // moved.
kono
parents:
diff changeset
1291 if (_M_begin())
kono
parents:
diff changeset
1292 _M_buckets[_M_bucket_index(_M_begin())] = &_M_before_begin;
kono
parents:
diff changeset
1293
kono
parents:
diff changeset
1294 __ht._M_reset();
kono
parents:
diff changeset
1295 }
kono
parents:
diff changeset
1296
kono
parents:
diff changeset
1297 template<typename _Key, typename _Value,
kono
parents:
diff changeset
1298 typename _Alloc, typename _ExtractKey, typename _Equal,
kono
parents:
diff changeset
1299 typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
kono
parents:
diff changeset
1300 typename _Traits>
kono
parents:
diff changeset
1301 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
kono
parents:
diff changeset
1302 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
kono
parents:
diff changeset
1303 _Hashtable(const _Hashtable& __ht, const allocator_type& __a)
kono
parents:
diff changeset
1304 : __hashtable_base(__ht),
kono
parents:
diff changeset
1305 __map_base(__ht),
kono
parents:
diff changeset
1306 __rehash_base(__ht),
kono
parents:
diff changeset
1307 __hashtable_alloc(__node_alloc_type(__a)),
kono
parents:
diff changeset
1308 _M_buckets(),
kono
parents:
diff changeset
1309 _M_bucket_count(__ht._M_bucket_count),
kono
parents:
diff changeset
1310 _M_element_count(__ht._M_element_count),
kono
parents:
diff changeset
1311 _M_rehash_policy(__ht._M_rehash_policy)
kono
parents:
diff changeset
1312 {
kono
parents:
diff changeset
1313 _M_assign(__ht,
kono
parents:
diff changeset
1314 [this](const __node_type* __n)
kono
parents:
diff changeset
1315 { return this->_M_allocate_node(__n->_M_v()); });
kono
parents:
diff changeset
1316 }
kono
parents:
diff changeset
1317
kono
parents:
diff changeset
1318 template<typename _Key, typename _Value,
kono
parents:
diff changeset
1319 typename _Alloc, typename _ExtractKey, typename _Equal,
kono
parents:
diff changeset
1320 typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
kono
parents:
diff changeset
1321 typename _Traits>
kono
parents:
diff changeset
1322 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
kono
parents:
diff changeset
1323 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
kono
parents:
diff changeset
1324 _Hashtable(_Hashtable&& __ht, const allocator_type& __a)
kono
parents:
diff changeset
1325 : __hashtable_base(__ht),
kono
parents:
diff changeset
1326 __map_base(__ht),
kono
parents:
diff changeset
1327 __rehash_base(__ht),
kono
parents:
diff changeset
1328 __hashtable_alloc(__node_alloc_type(__a)),
kono
parents:
diff changeset
1329 _M_buckets(nullptr),
kono
parents:
diff changeset
1330 _M_bucket_count(__ht._M_bucket_count),
kono
parents:
diff changeset
1331 _M_element_count(__ht._M_element_count),
kono
parents:
diff changeset
1332 _M_rehash_policy(__ht._M_rehash_policy)
kono
parents:
diff changeset
1333 {
kono
parents:
diff changeset
1334 if (__ht._M_node_allocator() == this->_M_node_allocator())
kono
parents:
diff changeset
1335 {
kono
parents:
diff changeset
1336 if (__ht._M_uses_single_bucket())
kono
parents:
diff changeset
1337 {
kono
parents:
diff changeset
1338 _M_buckets = &_M_single_bucket;
kono
parents:
diff changeset
1339 _M_single_bucket = __ht._M_single_bucket;
kono
parents:
diff changeset
1340 }
kono
parents:
diff changeset
1341 else
kono
parents:
diff changeset
1342 _M_buckets = __ht._M_buckets;
kono
parents:
diff changeset
1343
kono
parents:
diff changeset
1344 _M_before_begin._M_nxt = __ht._M_before_begin._M_nxt;
kono
parents:
diff changeset
1345 // Update, if necessary, bucket pointing to before begin that hasn't
kono
parents:
diff changeset
1346 // moved.
kono
parents:
diff changeset
1347 if (_M_begin())
kono
parents:
diff changeset
1348 _M_buckets[_M_bucket_index(_M_begin())] = &_M_before_begin;
kono
parents:
diff changeset
1349 __ht._M_reset();
kono
parents:
diff changeset
1350 }
kono
parents:
diff changeset
1351 else
kono
parents:
diff changeset
1352 {
kono
parents:
diff changeset
1353 _M_assign(__ht,
kono
parents:
diff changeset
1354 [this](__node_type* __n)
kono
parents:
diff changeset
1355 {
kono
parents:
diff changeset
1356 return this->_M_allocate_node(
kono
parents:
diff changeset
1357 std::move_if_noexcept(__n->_M_v()));
kono
parents:
diff changeset
1358 });
kono
parents:
diff changeset
1359 __ht.clear();
kono
parents:
diff changeset
1360 }
kono
parents:
diff changeset
1361 }
kono
parents:
diff changeset
1362
kono
parents:
diff changeset
1363 template<typename _Key, typename _Value,
kono
parents:
diff changeset
1364 typename _Alloc, typename _ExtractKey, typename _Equal,
kono
parents:
diff changeset
1365 typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
kono
parents:
diff changeset
1366 typename _Traits>
kono
parents:
diff changeset
1367 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
kono
parents:
diff changeset
1368 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
kono
parents:
diff changeset
1369 ~_Hashtable() noexcept
kono
parents:
diff changeset
1370 {
kono
parents:
diff changeset
1371 clear();
kono
parents:
diff changeset
1372 _M_deallocate_buckets();
kono
parents:
diff changeset
1373 }
kono
parents:
diff changeset
1374
kono
parents:
diff changeset
1375 template<typename _Key, typename _Value,
kono
parents:
diff changeset
1376 typename _Alloc, typename _ExtractKey, typename _Equal,
kono
parents:
diff changeset
1377 typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
kono
parents:
diff changeset
1378 typename _Traits>
kono
parents:
diff changeset
1379 void
kono
parents:
diff changeset
1380 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
kono
parents:
diff changeset
1381 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
kono
parents:
diff changeset
1382 swap(_Hashtable& __x)
kono
parents:
diff changeset
1383 noexcept(__and_<__is_nothrow_swappable<_H1>,
kono
parents:
diff changeset
1384 __is_nothrow_swappable<_Equal>>::value)
kono
parents:
diff changeset
1385 {
kono
parents:
diff changeset
1386 // The only base class with member variables is hash_code_base.
kono
parents:
diff changeset
1387 // We define _Hash_code_base::_M_swap because different
kono
parents:
diff changeset
1388 // specializations have different members.
kono
parents:
diff changeset
1389 this->_M_swap(__x);
kono
parents:
diff changeset
1390
kono
parents:
diff changeset
1391 std::__alloc_on_swap(this->_M_node_allocator(), __x._M_node_allocator());
kono
parents:
diff changeset
1392 std::swap(_M_rehash_policy, __x._M_rehash_policy);
kono
parents:
diff changeset
1393
kono
parents:
diff changeset
1394 // Deal properly with potentially moved instances.
kono
parents:
diff changeset
1395 if (this->_M_uses_single_bucket())
kono
parents:
diff changeset
1396 {
kono
parents:
diff changeset
1397 if (!__x._M_uses_single_bucket())
kono
parents:
diff changeset
1398 {
kono
parents:
diff changeset
1399 _M_buckets = __x._M_buckets;
kono
parents:
diff changeset
1400 __x._M_buckets = &__x._M_single_bucket;
kono
parents:
diff changeset
1401 }
kono
parents:
diff changeset
1402 }
kono
parents:
diff changeset
1403 else if (__x._M_uses_single_bucket())
kono
parents:
diff changeset
1404 {
kono
parents:
diff changeset
1405 __x._M_buckets = _M_buckets;
kono
parents:
diff changeset
1406 _M_buckets = &_M_single_bucket;
kono
parents:
diff changeset
1407 }
kono
parents:
diff changeset
1408 else
kono
parents:
diff changeset
1409 std::swap(_M_buckets, __x._M_buckets);
kono
parents:
diff changeset
1410
kono
parents:
diff changeset
1411 std::swap(_M_bucket_count, __x._M_bucket_count);
kono
parents:
diff changeset
1412 std::swap(_M_before_begin._M_nxt, __x._M_before_begin._M_nxt);
kono
parents:
diff changeset
1413 std::swap(_M_element_count, __x._M_element_count);
kono
parents:
diff changeset
1414 std::swap(_M_single_bucket, __x._M_single_bucket);
kono
parents:
diff changeset
1415
kono
parents:
diff changeset
1416 // Fix buckets containing the _M_before_begin pointers that can't be
kono
parents:
diff changeset
1417 // swapped.
kono
parents:
diff changeset
1418 if (_M_begin())
kono
parents:
diff changeset
1419 _M_buckets[_M_bucket_index(_M_begin())] = &_M_before_begin;
kono
parents:
diff changeset
1420
kono
parents:
diff changeset
1421 if (__x._M_begin())
kono
parents:
diff changeset
1422 __x._M_buckets[__x._M_bucket_index(__x._M_begin())]
kono
parents:
diff changeset
1423 = &__x._M_before_begin;
kono
parents:
diff changeset
1424 }
kono
parents:
diff changeset
1425
kono
parents:
diff changeset
1426 template<typename _Key, typename _Value,
kono
parents:
diff changeset
1427 typename _Alloc, typename _ExtractKey, typename _Equal,
kono
parents:
diff changeset
1428 typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
kono
parents:
diff changeset
1429 typename _Traits>
kono
parents:
diff changeset
1430 auto
kono
parents:
diff changeset
1431 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
kono
parents:
diff changeset
1432 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
kono
parents:
diff changeset
1433 find(const key_type& __k)
kono
parents:
diff changeset
1434 -> iterator
kono
parents:
diff changeset
1435 {
kono
parents:
diff changeset
1436 __hash_code __code = this->_M_hash_code(__k);
kono
parents:
diff changeset
1437 std::size_t __n = _M_bucket_index(__k, __code);
kono
parents:
diff changeset
1438 __node_type* __p = _M_find_node(__n, __k, __code);
kono
parents:
diff changeset
1439 return __p ? iterator(__p) : end();
kono
parents:
diff changeset
1440 }
kono
parents:
diff changeset
1441
kono
parents:
diff changeset
1442 template<typename _Key, typename _Value,
kono
parents:
diff changeset
1443 typename _Alloc, typename _ExtractKey, typename _Equal,
kono
parents:
diff changeset
1444 typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
kono
parents:
diff changeset
1445 typename _Traits>
kono
parents:
diff changeset
1446 auto
kono
parents:
diff changeset
1447 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
kono
parents:
diff changeset
1448 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
kono
parents:
diff changeset
1449 find(const key_type& __k) const
kono
parents:
diff changeset
1450 -> const_iterator
kono
parents:
diff changeset
1451 {
kono
parents:
diff changeset
1452 __hash_code __code = this->_M_hash_code(__k);
kono
parents:
diff changeset
1453 std::size_t __n = _M_bucket_index(__k, __code);
kono
parents:
diff changeset
1454 __node_type* __p = _M_find_node(__n, __k, __code);
kono
parents:
diff changeset
1455 return __p ? const_iterator(__p) : end();
kono
parents:
diff changeset
1456 }
kono
parents:
diff changeset
1457
kono
parents:
diff changeset
1458 template<typename _Key, typename _Value,
kono
parents:
diff changeset
1459 typename _Alloc, typename _ExtractKey, typename _Equal,
kono
parents:
diff changeset
1460 typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
kono
parents:
diff changeset
1461 typename _Traits>
kono
parents:
diff changeset
1462 auto
kono
parents:
diff changeset
1463 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
kono
parents:
diff changeset
1464 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
kono
parents:
diff changeset
1465 count(const key_type& __k) const
kono
parents:
diff changeset
1466 -> size_type
kono
parents:
diff changeset
1467 {
kono
parents:
diff changeset
1468 __hash_code __code = this->_M_hash_code(__k);
kono
parents:
diff changeset
1469 std::size_t __n = _M_bucket_index(__k, __code);
kono
parents:
diff changeset
1470 __node_type* __p = _M_bucket_begin(__n);
kono
parents:
diff changeset
1471 if (!__p)
kono
parents:
diff changeset
1472 return 0;
kono
parents:
diff changeset
1473
kono
parents:
diff changeset
1474 std::size_t __result = 0;
kono
parents:
diff changeset
1475 for (;; __p = __p->_M_next())
kono
parents:
diff changeset
1476 {
kono
parents:
diff changeset
1477 if (this->_M_equals(__k, __code, __p))
kono
parents:
diff changeset
1478 ++__result;
kono
parents:
diff changeset
1479 else if (__result)
kono
parents:
diff changeset
1480 // All equivalent values are next to each other, if we
kono
parents:
diff changeset
1481 // found a non-equivalent value after an equivalent one it
kono
parents:
diff changeset
1482 // means that we won't find any new equivalent value.
kono
parents:
diff changeset
1483 break;
kono
parents:
diff changeset
1484 if (!__p->_M_nxt || _M_bucket_index(__p->_M_next()) != __n)
kono
parents:
diff changeset
1485 break;
kono
parents:
diff changeset
1486 }
kono
parents:
diff changeset
1487 return __result;
kono
parents:
diff changeset
1488 }
kono
parents:
diff changeset
1489
kono
parents:
diff changeset
1490 template<typename _Key, typename _Value,
kono
parents:
diff changeset
1491 typename _Alloc, typename _ExtractKey, typename _Equal,
kono
parents:
diff changeset
1492 typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
kono
parents:
diff changeset
1493 typename _Traits>
kono
parents:
diff changeset
1494 auto
kono
parents:
diff changeset
1495 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
kono
parents:
diff changeset
1496 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
kono
parents:
diff changeset
1497 equal_range(const key_type& __k)
kono
parents:
diff changeset
1498 -> pair<iterator, iterator>
kono
parents:
diff changeset
1499 {
kono
parents:
diff changeset
1500 __hash_code __code = this->_M_hash_code(__k);
kono
parents:
diff changeset
1501 std::size_t __n = _M_bucket_index(__k, __code);
kono
parents:
diff changeset
1502 __node_type* __p = _M_find_node(__n, __k, __code);
kono
parents:
diff changeset
1503
kono
parents:
diff changeset
1504 if (__p)
kono
parents:
diff changeset
1505 {
kono
parents:
diff changeset
1506 __node_type* __p1 = __p->_M_next();
kono
parents:
diff changeset
1507 while (__p1 && _M_bucket_index(__p1) == __n
kono
parents:
diff changeset
1508 && this->_M_equals(__k, __code, __p1))
kono
parents:
diff changeset
1509 __p1 = __p1->_M_next();
kono
parents:
diff changeset
1510
kono
parents:
diff changeset
1511 return std::make_pair(iterator(__p), iterator(__p1));
kono
parents:
diff changeset
1512 }
kono
parents:
diff changeset
1513 else
kono
parents:
diff changeset
1514 return std::make_pair(end(), end());
kono
parents:
diff changeset
1515 }
kono
parents:
diff changeset
1516
kono
parents:
diff changeset
1517 template<typename _Key, typename _Value,
kono
parents:
diff changeset
1518 typename _Alloc, typename _ExtractKey, typename _Equal,
kono
parents:
diff changeset
1519 typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
kono
parents:
diff changeset
1520 typename _Traits>
kono
parents:
diff changeset
1521 auto
kono
parents:
diff changeset
1522 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
kono
parents:
diff changeset
1523 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
kono
parents:
diff changeset
1524 equal_range(const key_type& __k) const
kono
parents:
diff changeset
1525 -> pair<const_iterator, const_iterator>
kono
parents:
diff changeset
1526 {
kono
parents:
diff changeset
1527 __hash_code __code = this->_M_hash_code(__k);
kono
parents:
diff changeset
1528 std::size_t __n = _M_bucket_index(__k, __code);
kono
parents:
diff changeset
1529 __node_type* __p = _M_find_node(__n, __k, __code);
kono
parents:
diff changeset
1530
kono
parents:
diff changeset
1531 if (__p)
kono
parents:
diff changeset
1532 {
kono
parents:
diff changeset
1533 __node_type* __p1 = __p->_M_next();
kono
parents:
diff changeset
1534 while (__p1 && _M_bucket_index(__p1) == __n
kono
parents:
diff changeset
1535 && this->_M_equals(__k, __code, __p1))
kono
parents:
diff changeset
1536 __p1 = __p1->_M_next();
kono
parents:
diff changeset
1537
kono
parents:
diff changeset
1538 return std::make_pair(const_iterator(__p), const_iterator(__p1));
kono
parents:
diff changeset
1539 }
kono
parents:
diff changeset
1540 else
kono
parents:
diff changeset
1541 return std::make_pair(end(), end());
kono
parents:
diff changeset
1542 }
kono
parents:
diff changeset
1543
kono
parents:
diff changeset
1544 // Find the node whose key compares equal to k in the bucket n.
kono
parents:
diff changeset
1545 // Return nullptr if no node is found.
kono
parents:
diff changeset
1546 template<typename _Key, typename _Value,
kono
parents:
diff changeset
1547 typename _Alloc, typename _ExtractKey, typename _Equal,
kono
parents:
diff changeset
1548 typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
kono
parents:
diff changeset
1549 typename _Traits>
kono
parents:
diff changeset
1550 auto
kono
parents:
diff changeset
1551 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
kono
parents:
diff changeset
1552 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
kono
parents:
diff changeset
1553 _M_find_before_node(size_type __n, const key_type& __k,
kono
parents:
diff changeset
1554 __hash_code __code) const
kono
parents:
diff changeset
1555 -> __node_base*
kono
parents:
diff changeset
1556 {
kono
parents:
diff changeset
1557 __node_base* __prev_p = _M_buckets[__n];
kono
parents:
diff changeset
1558 if (!__prev_p)
kono
parents:
diff changeset
1559 return nullptr;
kono
parents:
diff changeset
1560
kono
parents:
diff changeset
1561 for (__node_type* __p = static_cast<__node_type*>(__prev_p->_M_nxt);;
kono
parents:
diff changeset
1562 __p = __p->_M_next())
kono
parents:
diff changeset
1563 {
kono
parents:
diff changeset
1564 if (this->_M_equals(__k, __code, __p))
kono
parents:
diff changeset
1565 return __prev_p;
kono
parents:
diff changeset
1566
kono
parents:
diff changeset
1567 if (!__p->_M_nxt || _M_bucket_index(__p->_M_next()) != __n)
kono
parents:
diff changeset
1568 break;
kono
parents:
diff changeset
1569 __prev_p = __p;
kono
parents:
diff changeset
1570 }
kono
parents:
diff changeset
1571 return nullptr;
kono
parents:
diff changeset
1572 }
kono
parents:
diff changeset
1573
kono
parents:
diff changeset
1574 template<typename _Key, typename _Value,
kono
parents:
diff changeset
1575 typename _Alloc, typename _ExtractKey, typename _Equal,
kono
parents:
diff changeset
1576 typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
kono
parents:
diff changeset
1577 typename _Traits>
kono
parents:
diff changeset
1578 void
kono
parents:
diff changeset
1579 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
kono
parents:
diff changeset
1580 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
kono
parents:
diff changeset
1581 _M_insert_bucket_begin(size_type __bkt, __node_type* __node)
kono
parents:
diff changeset
1582 {
kono
parents:
diff changeset
1583 if (_M_buckets[__bkt])
kono
parents:
diff changeset
1584 {
kono
parents:
diff changeset
1585 // Bucket is not empty, we just need to insert the new node
kono
parents:
diff changeset
1586 // after the bucket before begin.
kono
parents:
diff changeset
1587 __node->_M_nxt = _M_buckets[__bkt]->_M_nxt;
kono
parents:
diff changeset
1588 _M_buckets[__bkt]->_M_nxt = __node;
kono
parents:
diff changeset
1589 }
kono
parents:
diff changeset
1590 else
kono
parents:
diff changeset
1591 {
kono
parents:
diff changeset
1592 // The bucket is empty, the new node is inserted at the
kono
parents:
diff changeset
1593 // beginning of the singly-linked list and the bucket will
kono
parents:
diff changeset
1594 // contain _M_before_begin pointer.
kono
parents:
diff changeset
1595 __node->_M_nxt = _M_before_begin._M_nxt;
kono
parents:
diff changeset
1596 _M_before_begin._M_nxt = __node;
kono
parents:
diff changeset
1597 if (__node->_M_nxt)
kono
parents:
diff changeset
1598 // We must update former begin bucket that is pointing to
kono
parents:
diff changeset
1599 // _M_before_begin.
kono
parents:
diff changeset
1600 _M_buckets[_M_bucket_index(__node->_M_next())] = __node;
kono
parents:
diff changeset
1601 _M_buckets[__bkt] = &_M_before_begin;
kono
parents:
diff changeset
1602 }
kono
parents:
diff changeset
1603 }
kono
parents:
diff changeset
1604
kono
parents:
diff changeset
1605 template<typename _Key, typename _Value,
kono
parents:
diff changeset
1606 typename _Alloc, typename _ExtractKey, typename _Equal,
kono
parents:
diff changeset
1607 typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
kono
parents:
diff changeset
1608 typename _Traits>
kono
parents:
diff changeset
1609 void
kono
parents:
diff changeset
1610 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
kono
parents:
diff changeset
1611 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
kono
parents:
diff changeset
1612 _M_remove_bucket_begin(size_type __bkt, __node_type* __next,
kono
parents:
diff changeset
1613 size_type __next_bkt)
kono
parents:
diff changeset
1614 {
kono
parents:
diff changeset
1615 if (!__next || __next_bkt != __bkt)
kono
parents:
diff changeset
1616 {
kono
parents:
diff changeset
1617 // Bucket is now empty
kono
parents:
diff changeset
1618 // First update next bucket if any
kono
parents:
diff changeset
1619 if (__next)
kono
parents:
diff changeset
1620 _M_buckets[__next_bkt] = _M_buckets[__bkt];
kono
parents:
diff changeset
1621
kono
parents:
diff changeset
1622 // Second update before begin node if necessary
kono
parents:
diff changeset
1623 if (&_M_before_begin == _M_buckets[__bkt])
kono
parents:
diff changeset
1624 _M_before_begin._M_nxt = __next;
kono
parents:
diff changeset
1625 _M_buckets[__bkt] = nullptr;
kono
parents:
diff changeset
1626 }
kono
parents:
diff changeset
1627 }
kono
parents:
diff changeset
1628
kono
parents:
diff changeset
1629 template<typename _Key, typename _Value,
kono
parents:
diff changeset
1630 typename _Alloc, typename _ExtractKey, typename _Equal,
kono
parents:
diff changeset
1631 typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
kono
parents:
diff changeset
1632 typename _Traits>
kono
parents:
diff changeset
1633 auto
kono
parents:
diff changeset
1634 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
kono
parents:
diff changeset
1635 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
kono
parents:
diff changeset
1636 _M_get_previous_node(size_type __bkt, __node_base* __n)
kono
parents:
diff changeset
1637 -> __node_base*
kono
parents:
diff changeset
1638 {
kono
parents:
diff changeset
1639 __node_base* __prev_n = _M_buckets[__bkt];
kono
parents:
diff changeset
1640 while (__prev_n->_M_nxt != __n)
kono
parents:
diff changeset
1641 __prev_n = __prev_n->_M_nxt;
kono
parents:
diff changeset
1642 return __prev_n;
kono
parents:
diff changeset
1643 }
kono
parents:
diff changeset
1644
kono
parents:
diff changeset
1645 template<typename _Key, typename _Value,
kono
parents:
diff changeset
1646 typename _Alloc, typename _ExtractKey, typename _Equal,
kono
parents:
diff changeset
1647 typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
kono
parents:
diff changeset
1648 typename _Traits>
kono
parents:
diff changeset
1649 template<typename... _Args>
kono
parents:
diff changeset
1650 auto
kono
parents:
diff changeset
1651 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
kono
parents:
diff changeset
1652 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
kono
parents:
diff changeset
1653 _M_emplace(std::true_type, _Args&&... __args)
kono
parents:
diff changeset
1654 -> pair<iterator, bool>
kono
parents:
diff changeset
1655 {
kono
parents:
diff changeset
1656 // First build the node to get access to the hash code
kono
parents:
diff changeset
1657 __node_type* __node = this->_M_allocate_node(std::forward<_Args>(__args)...);
kono
parents:
diff changeset
1658 const key_type& __k = this->_M_extract()(__node->_M_v());
kono
parents:
diff changeset
1659 __hash_code __code;
kono
parents:
diff changeset
1660 __try
kono
parents:
diff changeset
1661 {
kono
parents:
diff changeset
1662 __code = this->_M_hash_code(__k);
kono
parents:
diff changeset
1663 }
kono
parents:
diff changeset
1664 __catch(...)
kono
parents:
diff changeset
1665 {
kono
parents:
diff changeset
1666 this->_M_deallocate_node(__node);
kono
parents:
diff changeset
1667 __throw_exception_again;
kono
parents:
diff changeset
1668 }
kono
parents:
diff changeset
1669
kono
parents:
diff changeset
1670 size_type __bkt = _M_bucket_index(__k, __code);
kono
parents:
diff changeset
1671 if (__node_type* __p = _M_find_node(__bkt, __k, __code))
kono
parents:
diff changeset
1672 {
kono
parents:
diff changeset
1673 // There is already an equivalent node, no insertion
kono
parents:
diff changeset
1674 this->_M_deallocate_node(__node);
kono
parents:
diff changeset
1675 return std::make_pair(iterator(__p), false);
kono
parents:
diff changeset
1676 }
kono
parents:
diff changeset
1677
kono
parents:
diff changeset
1678 // Insert the node
kono
parents:
diff changeset
1679 return std::make_pair(_M_insert_unique_node(__bkt, __code, __node),
kono
parents:
diff changeset
1680 true);
kono
parents:
diff changeset
1681 }
kono
parents:
diff changeset
1682
kono
parents:
diff changeset
1683 template<typename _Key, typename _Value,
kono
parents:
diff changeset
1684 typename _Alloc, typename _ExtractKey, typename _Equal,
kono
parents:
diff changeset
1685 typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
kono
parents:
diff changeset
1686 typename _Traits>
kono
parents:
diff changeset
1687 template<typename... _Args>
kono
parents:
diff changeset
1688 auto
kono
parents:
diff changeset
1689 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
kono
parents:
diff changeset
1690 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
kono
parents:
diff changeset
1691 _M_emplace(const_iterator __hint, std::false_type, _Args&&... __args)
kono
parents:
diff changeset
1692 -> iterator
kono
parents:
diff changeset
1693 {
kono
parents:
diff changeset
1694 // First build the node to get its hash code.
kono
parents:
diff changeset
1695 __node_type* __node =
kono
parents:
diff changeset
1696 this->_M_allocate_node(std::forward<_Args>(__args)...);
kono
parents:
diff changeset
1697
kono
parents:
diff changeset
1698 __hash_code __code;
kono
parents:
diff changeset
1699 __try
kono
parents:
diff changeset
1700 {
kono
parents:
diff changeset
1701 __code = this->_M_hash_code(this->_M_extract()(__node->_M_v()));
kono
parents:
diff changeset
1702 }
kono
parents:
diff changeset
1703 __catch(...)
kono
parents:
diff changeset
1704 {
kono
parents:
diff changeset
1705 this->_M_deallocate_node(__node);
kono
parents:
diff changeset
1706 __throw_exception_again;
kono
parents:
diff changeset
1707 }
kono
parents:
diff changeset
1708
kono
parents:
diff changeset
1709 return _M_insert_multi_node(__hint._M_cur, __code, __node);
kono
parents:
diff changeset
1710 }
kono
parents:
diff changeset
1711
kono
parents:
diff changeset
1712 template<typename _Key, typename _Value,
kono
parents:
diff changeset
1713 typename _Alloc, typename _ExtractKey, typename _Equal,
kono
parents:
diff changeset
1714 typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
kono
parents:
diff changeset
1715 typename _Traits>
kono
parents:
diff changeset
1716 auto
kono
parents:
diff changeset
1717 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
kono
parents:
diff changeset
1718 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
kono
parents:
diff changeset
1719 _M_insert_unique_node(size_type __bkt, __hash_code __code,
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1720 __node_type* __node, size_type __n_elt)
111
kono
parents:
diff changeset
1721 -> iterator
kono
parents:
diff changeset
1722 {
kono
parents:
diff changeset
1723 const __rehash_state& __saved_state = _M_rehash_policy._M_state();
kono
parents:
diff changeset
1724 std::pair<bool, std::size_t> __do_rehash
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1725 = _M_rehash_policy._M_need_rehash(_M_bucket_count, _M_element_count,
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1726 __n_elt);
111
kono
parents:
diff changeset
1727
kono
parents:
diff changeset
1728 __try
kono
parents:
diff changeset
1729 {
kono
parents:
diff changeset
1730 if (__do_rehash.first)
kono
parents:
diff changeset
1731 {
kono
parents:
diff changeset
1732 _M_rehash(__do_rehash.second, __saved_state);
kono
parents:
diff changeset
1733 __bkt = _M_bucket_index(this->_M_extract()(__node->_M_v()), __code);
kono
parents:
diff changeset
1734 }
kono
parents:
diff changeset
1735
kono
parents:
diff changeset
1736 this->_M_store_code(__node, __code);
kono
parents:
diff changeset
1737
kono
parents:
diff changeset
1738 // Always insert at the beginning of the bucket.
kono
parents:
diff changeset
1739 _M_insert_bucket_begin(__bkt, __node);
kono
parents:
diff changeset
1740 ++_M_element_count;
kono
parents:
diff changeset
1741 return iterator(__node);
kono
parents:
diff changeset
1742 }
kono
parents:
diff changeset
1743 __catch(...)
kono
parents:
diff changeset
1744 {
kono
parents:
diff changeset
1745 this->_M_deallocate_node(__node);
kono
parents:
diff changeset
1746 __throw_exception_again;
kono
parents:
diff changeset
1747 }
kono
parents:
diff changeset
1748 }
kono
parents:
diff changeset
1749
kono
parents:
diff changeset
1750 // Insert node, in bucket bkt if no rehash (assumes no element with its key
kono
parents:
diff changeset
1751 // already present). Take ownership of the node, deallocate it on exception.
kono
parents:
diff changeset
1752 template<typename _Key, typename _Value,
kono
parents:
diff changeset
1753 typename _Alloc, typename _ExtractKey, typename _Equal,
kono
parents:
diff changeset
1754 typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
kono
parents:
diff changeset
1755 typename _Traits>
kono
parents:
diff changeset
1756 auto
kono
parents:
diff changeset
1757 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
kono
parents:
diff changeset
1758 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
kono
parents:
diff changeset
1759 _M_insert_multi_node(__node_type* __hint, __hash_code __code,
kono
parents:
diff changeset
1760 __node_type* __node)
kono
parents:
diff changeset
1761 -> iterator
kono
parents:
diff changeset
1762 {
kono
parents:
diff changeset
1763 const __rehash_state& __saved_state = _M_rehash_policy._M_state();
kono
parents:
diff changeset
1764 std::pair<bool, std::size_t> __do_rehash
kono
parents:
diff changeset
1765 = _M_rehash_policy._M_need_rehash(_M_bucket_count, _M_element_count, 1);
kono
parents:
diff changeset
1766
kono
parents:
diff changeset
1767 __try
kono
parents:
diff changeset
1768 {
kono
parents:
diff changeset
1769 if (__do_rehash.first)
kono
parents:
diff changeset
1770 _M_rehash(__do_rehash.second, __saved_state);
kono
parents:
diff changeset
1771
kono
parents:
diff changeset
1772 this->_M_store_code(__node, __code);
kono
parents:
diff changeset
1773 const key_type& __k = this->_M_extract()(__node->_M_v());
kono
parents:
diff changeset
1774 size_type __bkt = _M_bucket_index(__k, __code);
kono
parents:
diff changeset
1775
kono
parents:
diff changeset
1776 // Find the node before an equivalent one or use hint if it exists and
kono
parents:
diff changeset
1777 // if it is equivalent.
kono
parents:
diff changeset
1778 __node_base* __prev
kono
parents:
diff changeset
1779 = __builtin_expect(__hint != nullptr, false)
kono
parents:
diff changeset
1780 && this->_M_equals(__k, __code, __hint)
kono
parents:
diff changeset
1781 ? __hint
kono
parents:
diff changeset
1782 : _M_find_before_node(__bkt, __k, __code);
kono
parents:
diff changeset
1783 if (__prev)
kono
parents:
diff changeset
1784 {
kono
parents:
diff changeset
1785 // Insert after the node before the equivalent one.
kono
parents:
diff changeset
1786 __node->_M_nxt = __prev->_M_nxt;
kono
parents:
diff changeset
1787 __prev->_M_nxt = __node;
kono
parents:
diff changeset
1788 if (__builtin_expect(__prev == __hint, false))
kono
parents:
diff changeset
1789 // hint might be the last bucket node, in this case we need to
kono
parents:
diff changeset
1790 // update next bucket.
kono
parents:
diff changeset
1791 if (__node->_M_nxt
kono
parents:
diff changeset
1792 && !this->_M_equals(__k, __code, __node->_M_next()))
kono
parents:
diff changeset
1793 {
kono
parents:
diff changeset
1794 size_type __next_bkt = _M_bucket_index(__node->_M_next());
kono
parents:
diff changeset
1795 if (__next_bkt != __bkt)
kono
parents:
diff changeset
1796 _M_buckets[__next_bkt] = __node;
kono
parents:
diff changeset
1797 }
kono
parents:
diff changeset
1798 }
kono
parents:
diff changeset
1799 else
kono
parents:
diff changeset
1800 // The inserted node has no equivalent in the
kono
parents:
diff changeset
1801 // hashtable. We must insert the new node at the
kono
parents:
diff changeset
1802 // beginning of the bucket to preserve equivalent
kono
parents:
diff changeset
1803 // elements' relative positions.
kono
parents:
diff changeset
1804 _M_insert_bucket_begin(__bkt, __node);
kono
parents:
diff changeset
1805 ++_M_element_count;
kono
parents:
diff changeset
1806 return iterator(__node);
kono
parents:
diff changeset
1807 }
kono
parents:
diff changeset
1808 __catch(...)
kono
parents:
diff changeset
1809 {
kono
parents:
diff changeset
1810 this->_M_deallocate_node(__node);
kono
parents:
diff changeset
1811 __throw_exception_again;
kono
parents:
diff changeset
1812 }
kono
parents:
diff changeset
1813 }
kono
parents:
diff changeset
1814
kono
parents:
diff changeset
1815 // Insert v if no element with its key is already present.
kono
parents:
diff changeset
1816 template<typename _Key, typename _Value,
kono
parents:
diff changeset
1817 typename _Alloc, typename _ExtractKey, typename _Equal,
kono
parents:
diff changeset
1818 typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
kono
parents:
diff changeset
1819 typename _Traits>
kono
parents:
diff changeset
1820 template<typename _Arg, typename _NodeGenerator>
kono
parents:
diff changeset
1821 auto
kono
parents:
diff changeset
1822 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
kono
parents:
diff changeset
1823 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1824 _M_insert(_Arg&& __v, const _NodeGenerator& __node_gen, true_type,
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1825 size_type __n_elt)
111
kono
parents:
diff changeset
1826 -> pair<iterator, bool>
kono
parents:
diff changeset
1827 {
kono
parents:
diff changeset
1828 const key_type& __k = this->_M_extract()(__v);
kono
parents:
diff changeset
1829 __hash_code __code = this->_M_hash_code(__k);
kono
parents:
diff changeset
1830 size_type __bkt = _M_bucket_index(__k, __code);
kono
parents:
diff changeset
1831
kono
parents:
diff changeset
1832 __node_type* __n = _M_find_node(__bkt, __k, __code);
kono
parents:
diff changeset
1833 if (__n)
kono
parents:
diff changeset
1834 return std::make_pair(iterator(__n), false);
kono
parents:
diff changeset
1835
kono
parents:
diff changeset
1836 __n = __node_gen(std::forward<_Arg>(__v));
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1837 return { _M_insert_unique_node(__bkt, __code, __n, __n_elt), true };
111
kono
parents:
diff changeset
1838 }
kono
parents:
diff changeset
1839
kono
parents:
diff changeset
1840 // Insert v unconditionally.
kono
parents:
diff changeset
1841 template<typename _Key, typename _Value,
kono
parents:
diff changeset
1842 typename _Alloc, typename _ExtractKey, typename _Equal,
kono
parents:
diff changeset
1843 typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
kono
parents:
diff changeset
1844 typename _Traits>
kono
parents:
diff changeset
1845 template<typename _Arg, typename _NodeGenerator>
kono
parents:
diff changeset
1846 auto
kono
parents:
diff changeset
1847 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
kono
parents:
diff changeset
1848 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
kono
parents:
diff changeset
1849 _M_insert(const_iterator __hint, _Arg&& __v,
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1850 const _NodeGenerator& __node_gen, false_type)
111
kono
parents:
diff changeset
1851 -> iterator
kono
parents:
diff changeset
1852 {
kono
parents:
diff changeset
1853 // First compute the hash code so that we don't do anything if it
kono
parents:
diff changeset
1854 // throws.
kono
parents:
diff changeset
1855 __hash_code __code = this->_M_hash_code(this->_M_extract()(__v));
kono
parents:
diff changeset
1856
kono
parents:
diff changeset
1857 // Second allocate new node so that we don't rehash if it throws.
kono
parents:
diff changeset
1858 __node_type* __node = __node_gen(std::forward<_Arg>(__v));
kono
parents:
diff changeset
1859
kono
parents:
diff changeset
1860 return _M_insert_multi_node(__hint._M_cur, __code, __node);
kono
parents:
diff changeset
1861 }
kono
parents:
diff changeset
1862
kono
parents:
diff changeset
1863 template<typename _Key, typename _Value,
kono
parents:
diff changeset
1864 typename _Alloc, typename _ExtractKey, typename _Equal,
kono
parents:
diff changeset
1865 typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
kono
parents:
diff changeset
1866 typename _Traits>
kono
parents:
diff changeset
1867 auto
kono
parents:
diff changeset
1868 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
kono
parents:
diff changeset
1869 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
kono
parents:
diff changeset
1870 erase(const_iterator __it)
kono
parents:
diff changeset
1871 -> iterator
kono
parents:
diff changeset
1872 {
kono
parents:
diff changeset
1873 __node_type* __n = __it._M_cur;
kono
parents:
diff changeset
1874 std::size_t __bkt = _M_bucket_index(__n);
kono
parents:
diff changeset
1875
kono
parents:
diff changeset
1876 // Look for previous node to unlink it from the erased one, this
kono
parents:
diff changeset
1877 // is why we need buckets to contain the before begin to make
kono
parents:
diff changeset
1878 // this search fast.
kono
parents:
diff changeset
1879 __node_base* __prev_n = _M_get_previous_node(__bkt, __n);
kono
parents:
diff changeset
1880 return _M_erase(__bkt, __prev_n, __n);
kono
parents:
diff changeset
1881 }
kono
parents:
diff changeset
1882
kono
parents:
diff changeset
1883 template<typename _Key, typename _Value,
kono
parents:
diff changeset
1884 typename _Alloc, typename _ExtractKey, typename _Equal,
kono
parents:
diff changeset
1885 typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
kono
parents:
diff changeset
1886 typename _Traits>
kono
parents:
diff changeset
1887 auto
kono
parents:
diff changeset
1888 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
kono
parents:
diff changeset
1889 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
kono
parents:
diff changeset
1890 _M_erase(size_type __bkt, __node_base* __prev_n, __node_type* __n)
kono
parents:
diff changeset
1891 -> iterator
kono
parents:
diff changeset
1892 {
kono
parents:
diff changeset
1893 if (__prev_n == _M_buckets[__bkt])
kono
parents:
diff changeset
1894 _M_remove_bucket_begin(__bkt, __n->_M_next(),
kono
parents:
diff changeset
1895 __n->_M_nxt ? _M_bucket_index(__n->_M_next()) : 0);
kono
parents:
diff changeset
1896 else if (__n->_M_nxt)
kono
parents:
diff changeset
1897 {
kono
parents:
diff changeset
1898 size_type __next_bkt = _M_bucket_index(__n->_M_next());
kono
parents:
diff changeset
1899 if (__next_bkt != __bkt)
kono
parents:
diff changeset
1900 _M_buckets[__next_bkt] = __prev_n;
kono
parents:
diff changeset
1901 }
kono
parents:
diff changeset
1902
kono
parents:
diff changeset
1903 __prev_n->_M_nxt = __n->_M_nxt;
kono
parents:
diff changeset
1904 iterator __result(__n->_M_next());
kono
parents:
diff changeset
1905 this->_M_deallocate_node(__n);
kono
parents:
diff changeset
1906 --_M_element_count;
kono
parents:
diff changeset
1907
kono
parents:
diff changeset
1908 return __result;
kono
parents:
diff changeset
1909 }
kono
parents:
diff changeset
1910
kono
parents:
diff changeset
1911 template<typename _Key, typename _Value,
kono
parents:
diff changeset
1912 typename _Alloc, typename _ExtractKey, typename _Equal,
kono
parents:
diff changeset
1913 typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
kono
parents:
diff changeset
1914 typename _Traits>
kono
parents:
diff changeset
1915 auto
kono
parents:
diff changeset
1916 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
kono
parents:
diff changeset
1917 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
kono
parents:
diff changeset
1918 _M_erase(std::true_type, const key_type& __k)
kono
parents:
diff changeset
1919 -> size_type
kono
parents:
diff changeset
1920 {
kono
parents:
diff changeset
1921 __hash_code __code = this->_M_hash_code(__k);
kono
parents:
diff changeset
1922 std::size_t __bkt = _M_bucket_index(__k, __code);
kono
parents:
diff changeset
1923
kono
parents:
diff changeset
1924 // Look for the node before the first matching node.
kono
parents:
diff changeset
1925 __node_base* __prev_n = _M_find_before_node(__bkt, __k, __code);
kono
parents:
diff changeset
1926 if (!__prev_n)
kono
parents:
diff changeset
1927 return 0;
kono
parents:
diff changeset
1928
kono
parents:
diff changeset
1929 // We found a matching node, erase it.
kono
parents:
diff changeset
1930 __node_type* __n = static_cast<__node_type*>(__prev_n->_M_nxt);
kono
parents:
diff changeset
1931 _M_erase(__bkt, __prev_n, __n);
kono
parents:
diff changeset
1932 return 1;
kono
parents:
diff changeset
1933 }
kono
parents:
diff changeset
1934
kono
parents:
diff changeset
1935 template<typename _Key, typename _Value,
kono
parents:
diff changeset
1936 typename _Alloc, typename _ExtractKey, typename _Equal,
kono
parents:
diff changeset
1937 typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
kono
parents:
diff changeset
1938 typename _Traits>
kono
parents:
diff changeset
1939 auto
kono
parents:
diff changeset
1940 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
kono
parents:
diff changeset
1941 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
kono
parents:
diff changeset
1942 _M_erase(std::false_type, const key_type& __k)
kono
parents:
diff changeset
1943 -> size_type
kono
parents:
diff changeset
1944 {
kono
parents:
diff changeset
1945 __hash_code __code = this->_M_hash_code(__k);
kono
parents:
diff changeset
1946 std::size_t __bkt = _M_bucket_index(__k, __code);
kono
parents:
diff changeset
1947
kono
parents:
diff changeset
1948 // Look for the node before the first matching node.
kono
parents:
diff changeset
1949 __node_base* __prev_n = _M_find_before_node(__bkt, __k, __code);
kono
parents:
diff changeset
1950 if (!__prev_n)
kono
parents:
diff changeset
1951 return 0;
kono
parents:
diff changeset
1952
kono
parents:
diff changeset
1953 // _GLIBCXX_RESOLVE_LIB_DEFECTS
kono
parents:
diff changeset
1954 // 526. Is it undefined if a function in the standard changes
kono
parents:
diff changeset
1955 // in parameters?
kono
parents:
diff changeset
1956 // We use one loop to find all matching nodes and another to deallocate
kono
parents:
diff changeset
1957 // them so that the key stays valid during the first loop. It might be
kono
parents:
diff changeset
1958 // invalidated indirectly when destroying nodes.
kono
parents:
diff changeset
1959 __node_type* __n = static_cast<__node_type*>(__prev_n->_M_nxt);
kono
parents:
diff changeset
1960 __node_type* __n_last = __n;
kono
parents:
diff changeset
1961 std::size_t __n_last_bkt = __bkt;
kono
parents:
diff changeset
1962 do
kono
parents:
diff changeset
1963 {
kono
parents:
diff changeset
1964 __n_last = __n_last->_M_next();
kono
parents:
diff changeset
1965 if (!__n_last)
kono
parents:
diff changeset
1966 break;
kono
parents:
diff changeset
1967 __n_last_bkt = _M_bucket_index(__n_last);
kono
parents:
diff changeset
1968 }
kono
parents:
diff changeset
1969 while (__n_last_bkt == __bkt && this->_M_equals(__k, __code, __n_last));
kono
parents:
diff changeset
1970
kono
parents:
diff changeset
1971 // Deallocate nodes.
kono
parents:
diff changeset
1972 size_type __result = 0;
kono
parents:
diff changeset
1973 do
kono
parents:
diff changeset
1974 {
kono
parents:
diff changeset
1975 __node_type* __p = __n->_M_next();
kono
parents:
diff changeset
1976 this->_M_deallocate_node(__n);
kono
parents:
diff changeset
1977 __n = __p;
kono
parents:
diff changeset
1978 ++__result;
kono
parents:
diff changeset
1979 --_M_element_count;
kono
parents:
diff changeset
1980 }
kono
parents:
diff changeset
1981 while (__n != __n_last);
kono
parents:
diff changeset
1982
kono
parents:
diff changeset
1983 if (__prev_n == _M_buckets[__bkt])
kono
parents:
diff changeset
1984 _M_remove_bucket_begin(__bkt, __n_last, __n_last_bkt);
kono
parents:
diff changeset
1985 else if (__n_last && __n_last_bkt != __bkt)
kono
parents:
diff changeset
1986 _M_buckets[__n_last_bkt] = __prev_n;
kono
parents:
diff changeset
1987 __prev_n->_M_nxt = __n_last;
kono
parents:
diff changeset
1988 return __result;
kono
parents:
diff changeset
1989 }
kono
parents:
diff changeset
1990
kono
parents:
diff changeset
1991 template<typename _Key, typename _Value,
kono
parents:
diff changeset
1992 typename _Alloc, typename _ExtractKey, typename _Equal,
kono
parents:
diff changeset
1993 typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
kono
parents:
diff changeset
1994 typename _Traits>
kono
parents:
diff changeset
1995 auto
kono
parents:
diff changeset
1996 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
kono
parents:
diff changeset
1997 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
kono
parents:
diff changeset
1998 erase(const_iterator __first, const_iterator __last)
kono
parents:
diff changeset
1999 -> iterator
kono
parents:
diff changeset
2000 {
kono
parents:
diff changeset
2001 __node_type* __n = __first._M_cur;
kono
parents:
diff changeset
2002 __node_type* __last_n = __last._M_cur;
kono
parents:
diff changeset
2003 if (__n == __last_n)
kono
parents:
diff changeset
2004 return iterator(__n);
kono
parents:
diff changeset
2005
kono
parents:
diff changeset
2006 std::size_t __bkt = _M_bucket_index(__n);
kono
parents:
diff changeset
2007
kono
parents:
diff changeset
2008 __node_base* __prev_n = _M_get_previous_node(__bkt, __n);
kono
parents:
diff changeset
2009 bool __is_bucket_begin = __n == _M_bucket_begin(__bkt);
kono
parents:
diff changeset
2010 std::size_t __n_bkt = __bkt;
kono
parents:
diff changeset
2011 for (;;)
kono
parents:
diff changeset
2012 {
kono
parents:
diff changeset
2013 do
kono
parents:
diff changeset
2014 {
kono
parents:
diff changeset
2015 __node_type* __tmp = __n;
kono
parents:
diff changeset
2016 __n = __n->_M_next();
kono
parents:
diff changeset
2017 this->_M_deallocate_node(__tmp);
kono
parents:
diff changeset
2018 --_M_element_count;
kono
parents:
diff changeset
2019 if (!__n)
kono
parents:
diff changeset
2020 break;
kono
parents:
diff changeset
2021 __n_bkt = _M_bucket_index(__n);
kono
parents:
diff changeset
2022 }
kono
parents:
diff changeset
2023 while (__n != __last_n && __n_bkt == __bkt);
kono
parents:
diff changeset
2024 if (__is_bucket_begin)
kono
parents:
diff changeset
2025 _M_remove_bucket_begin(__bkt, __n, __n_bkt);
kono
parents:
diff changeset
2026 if (__n == __last_n)
kono
parents:
diff changeset
2027 break;
kono
parents:
diff changeset
2028 __is_bucket_begin = true;
kono
parents:
diff changeset
2029 __bkt = __n_bkt;
kono
parents:
diff changeset
2030 }
kono
parents:
diff changeset
2031
kono
parents:
diff changeset
2032 if (__n && (__n_bkt != __bkt || __is_bucket_begin))
kono
parents:
diff changeset
2033 _M_buckets[__n_bkt] = __prev_n;
kono
parents:
diff changeset
2034 __prev_n->_M_nxt = __n;
kono
parents:
diff changeset
2035 return iterator(__n);
kono
parents:
diff changeset
2036 }
kono
parents:
diff changeset
2037
kono
parents:
diff changeset
2038 template<typename _Key, typename _Value,
kono
parents:
diff changeset
2039 typename _Alloc, typename _ExtractKey, typename _Equal,
kono
parents:
diff changeset
2040 typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
kono
parents:
diff changeset
2041 typename _Traits>
kono
parents:
diff changeset
2042 void
kono
parents:
diff changeset
2043 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
kono
parents:
diff changeset
2044 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
kono
parents:
diff changeset
2045 clear() noexcept
kono
parents:
diff changeset
2046 {
kono
parents:
diff changeset
2047 this->_M_deallocate_nodes(_M_begin());
kono
parents:
diff changeset
2048 __builtin_memset(_M_buckets, 0, _M_bucket_count * sizeof(__bucket_type));
kono
parents:
diff changeset
2049 _M_element_count = 0;
kono
parents:
diff changeset
2050 _M_before_begin._M_nxt = nullptr;
kono
parents:
diff changeset
2051 }
kono
parents:
diff changeset
2052
kono
parents:
diff changeset
2053 template<typename _Key, typename _Value,
kono
parents:
diff changeset
2054 typename _Alloc, typename _ExtractKey, typename _Equal,
kono
parents:
diff changeset
2055 typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
kono
parents:
diff changeset
2056 typename _Traits>
kono
parents:
diff changeset
2057 void
kono
parents:
diff changeset
2058 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
kono
parents:
diff changeset
2059 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
kono
parents:
diff changeset
2060 rehash(size_type __n)
kono
parents:
diff changeset
2061 {
kono
parents:
diff changeset
2062 const __rehash_state& __saved_state = _M_rehash_policy._M_state();
kono
parents:
diff changeset
2063 std::size_t __buckets
kono
parents:
diff changeset
2064 = std::max(_M_rehash_policy._M_bkt_for_elements(_M_element_count + 1),
kono
parents:
diff changeset
2065 __n);
kono
parents:
diff changeset
2066 __buckets = _M_rehash_policy._M_next_bkt(__buckets);
kono
parents:
diff changeset
2067
kono
parents:
diff changeset
2068 if (__buckets != _M_bucket_count)
kono
parents:
diff changeset
2069 _M_rehash(__buckets, __saved_state);
kono
parents:
diff changeset
2070 else
kono
parents:
diff changeset
2071 // No rehash, restore previous state to keep a consistent state.
kono
parents:
diff changeset
2072 _M_rehash_policy._M_reset(__saved_state);
kono
parents:
diff changeset
2073 }
kono
parents:
diff changeset
2074
kono
parents:
diff changeset
2075 template<typename _Key, typename _Value,
kono
parents:
diff changeset
2076 typename _Alloc, typename _ExtractKey, typename _Equal,
kono
parents:
diff changeset
2077 typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
kono
parents:
diff changeset
2078 typename _Traits>
kono
parents:
diff changeset
2079 void
kono
parents:
diff changeset
2080 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
kono
parents:
diff changeset
2081 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
kono
parents:
diff changeset
2082 _M_rehash(size_type __n, const __rehash_state& __state)
kono
parents:
diff changeset
2083 {
kono
parents:
diff changeset
2084 __try
kono
parents:
diff changeset
2085 {
kono
parents:
diff changeset
2086 _M_rehash_aux(__n, __unique_keys());
kono
parents:
diff changeset
2087 }
kono
parents:
diff changeset
2088 __catch(...)
kono
parents:
diff changeset
2089 {
kono
parents:
diff changeset
2090 // A failure here means that buckets allocation failed. We only
kono
parents:
diff changeset
2091 // have to restore hash policy previous state.
kono
parents:
diff changeset
2092 _M_rehash_policy._M_reset(__state);
kono
parents:
diff changeset
2093 __throw_exception_again;
kono
parents:
diff changeset
2094 }
kono
parents:
diff changeset
2095 }
kono
parents:
diff changeset
2096
kono
parents:
diff changeset
2097 // Rehash when there is no equivalent elements.
kono
parents:
diff changeset
2098 template<typename _Key, typename _Value,
kono
parents:
diff changeset
2099 typename _Alloc, typename _ExtractKey, typename _Equal,
kono
parents:
diff changeset
2100 typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
kono
parents:
diff changeset
2101 typename _Traits>
kono
parents:
diff changeset
2102 void
kono
parents:
diff changeset
2103 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
kono
parents:
diff changeset
2104 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
kono
parents:
diff changeset
2105 _M_rehash_aux(size_type __n, std::true_type)
kono
parents:
diff changeset
2106 {
kono
parents:
diff changeset
2107 __bucket_type* __new_buckets = _M_allocate_buckets(__n);
kono
parents:
diff changeset
2108 __node_type* __p = _M_begin();
kono
parents:
diff changeset
2109 _M_before_begin._M_nxt = nullptr;
kono
parents:
diff changeset
2110 std::size_t __bbegin_bkt = 0;
kono
parents:
diff changeset
2111 while (__p)
kono
parents:
diff changeset
2112 {
kono
parents:
diff changeset
2113 __node_type* __next = __p->_M_next();
kono
parents:
diff changeset
2114 std::size_t __bkt = __hash_code_base::_M_bucket_index(__p, __n);
kono
parents:
diff changeset
2115 if (!__new_buckets[__bkt])
kono
parents:
diff changeset
2116 {
kono
parents:
diff changeset
2117 __p->_M_nxt = _M_before_begin._M_nxt;
kono
parents:
diff changeset
2118 _M_before_begin._M_nxt = __p;
kono
parents:
diff changeset
2119 __new_buckets[__bkt] = &_M_before_begin;
kono
parents:
diff changeset
2120 if (__p->_M_nxt)
kono
parents:
diff changeset
2121 __new_buckets[__bbegin_bkt] = __p;
kono
parents:
diff changeset
2122 __bbegin_bkt = __bkt;
kono
parents:
diff changeset
2123 }
kono
parents:
diff changeset
2124 else
kono
parents:
diff changeset
2125 {
kono
parents:
diff changeset
2126 __p->_M_nxt = __new_buckets[__bkt]->_M_nxt;
kono
parents:
diff changeset
2127 __new_buckets[__bkt]->_M_nxt = __p;
kono
parents:
diff changeset
2128 }
kono
parents:
diff changeset
2129 __p = __next;
kono
parents:
diff changeset
2130 }
kono
parents:
diff changeset
2131
kono
parents:
diff changeset
2132 _M_deallocate_buckets();
kono
parents:
diff changeset
2133 _M_bucket_count = __n;
kono
parents:
diff changeset
2134 _M_buckets = __new_buckets;
kono
parents:
diff changeset
2135 }
kono
parents:
diff changeset
2136
kono
parents:
diff changeset
2137 // Rehash when there can be equivalent elements, preserve their relative
kono
parents:
diff changeset
2138 // order.
kono
parents:
diff changeset
2139 template<typename _Key, typename _Value,
kono
parents:
diff changeset
2140 typename _Alloc, typename _ExtractKey, typename _Equal,
kono
parents:
diff changeset
2141 typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
kono
parents:
diff changeset
2142 typename _Traits>
kono
parents:
diff changeset
2143 void
kono
parents:
diff changeset
2144 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
kono
parents:
diff changeset
2145 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
kono
parents:
diff changeset
2146 _M_rehash_aux(size_type __n, std::false_type)
kono
parents:
diff changeset
2147 {
kono
parents:
diff changeset
2148 __bucket_type* __new_buckets = _M_allocate_buckets(__n);
kono
parents:
diff changeset
2149
kono
parents:
diff changeset
2150 __node_type* __p = _M_begin();
kono
parents:
diff changeset
2151 _M_before_begin._M_nxt = nullptr;
kono
parents:
diff changeset
2152 std::size_t __bbegin_bkt = 0;
kono
parents:
diff changeset
2153 std::size_t __prev_bkt = 0;
kono
parents:
diff changeset
2154 __node_type* __prev_p = nullptr;
kono
parents:
diff changeset
2155 bool __check_bucket = false;
kono
parents:
diff changeset
2156
kono
parents:
diff changeset
2157 while (__p)
kono
parents:
diff changeset
2158 {
kono
parents:
diff changeset
2159 __node_type* __next = __p->_M_next();
kono
parents:
diff changeset
2160 std::size_t __bkt = __hash_code_base::_M_bucket_index(__p, __n);
kono
parents:
diff changeset
2161
kono
parents:
diff changeset
2162 if (__prev_p && __prev_bkt == __bkt)
kono
parents:
diff changeset
2163 {
kono
parents:
diff changeset
2164 // Previous insert was already in this bucket, we insert after
kono
parents:
diff changeset
2165 // the previously inserted one to preserve equivalent elements
kono
parents:
diff changeset
2166 // relative order.
kono
parents:
diff changeset
2167 __p->_M_nxt = __prev_p->_M_nxt;
kono
parents:
diff changeset
2168 __prev_p->_M_nxt = __p;
kono
parents:
diff changeset
2169
kono
parents:
diff changeset
2170 // Inserting after a node in a bucket require to check that we
kono
parents:
diff changeset
2171 // haven't change the bucket last node, in this case next
kono
parents:
diff changeset
2172 // bucket containing its before begin node must be updated. We
kono
parents:
diff changeset
2173 // schedule a check as soon as we move out of the sequence of
kono
parents:
diff changeset
2174 // equivalent nodes to limit the number of checks.
kono
parents:
diff changeset
2175 __check_bucket = true;
kono
parents:
diff changeset
2176 }
kono
parents:
diff changeset
2177 else
kono
parents:
diff changeset
2178 {
kono
parents:
diff changeset
2179 if (__check_bucket)
kono
parents:
diff changeset
2180 {
kono
parents:
diff changeset
2181 // Check if we shall update the next bucket because of
kono
parents:
diff changeset
2182 // insertions into __prev_bkt bucket.
kono
parents:
diff changeset
2183 if (__prev_p->_M_nxt)
kono
parents:
diff changeset
2184 {
kono
parents:
diff changeset
2185 std::size_t __next_bkt
kono
parents:
diff changeset
2186 = __hash_code_base::_M_bucket_index(__prev_p->_M_next(),
kono
parents:
diff changeset
2187 __n);
kono
parents:
diff changeset
2188 if (__next_bkt != __prev_bkt)
kono
parents:
diff changeset
2189 __new_buckets[__next_bkt] = __prev_p;
kono
parents:
diff changeset
2190 }
kono
parents:
diff changeset
2191 __check_bucket = false;
kono
parents:
diff changeset
2192 }
kono
parents:
diff changeset
2193
kono
parents:
diff changeset
2194 if (!__new_buckets[__bkt])
kono
parents:
diff changeset
2195 {
kono
parents:
diff changeset
2196 __p->_M_nxt = _M_before_begin._M_nxt;
kono
parents:
diff changeset
2197 _M_before_begin._M_nxt = __p;
kono
parents:
diff changeset
2198 __new_buckets[__bkt] = &_M_before_begin;
kono
parents:
diff changeset
2199 if (__p->_M_nxt)
kono
parents:
diff changeset
2200 __new_buckets[__bbegin_bkt] = __p;
kono
parents:
diff changeset
2201 __bbegin_bkt = __bkt;
kono
parents:
diff changeset
2202 }
kono
parents:
diff changeset
2203 else
kono
parents:
diff changeset
2204 {
kono
parents:
diff changeset
2205 __p->_M_nxt = __new_buckets[__bkt]->_M_nxt;
kono
parents:
diff changeset
2206 __new_buckets[__bkt]->_M_nxt = __p;
kono
parents:
diff changeset
2207 }
kono
parents:
diff changeset
2208 }
kono
parents:
diff changeset
2209 __prev_p = __p;
kono
parents:
diff changeset
2210 __prev_bkt = __bkt;
kono
parents:
diff changeset
2211 __p = __next;
kono
parents:
diff changeset
2212 }
kono
parents:
diff changeset
2213
kono
parents:
diff changeset
2214 if (__check_bucket && __prev_p->_M_nxt)
kono
parents:
diff changeset
2215 {
kono
parents:
diff changeset
2216 std::size_t __next_bkt
kono
parents:
diff changeset
2217 = __hash_code_base::_M_bucket_index(__prev_p->_M_next(), __n);
kono
parents:
diff changeset
2218 if (__next_bkt != __prev_bkt)
kono
parents:
diff changeset
2219 __new_buckets[__next_bkt] = __prev_p;
kono
parents:
diff changeset
2220 }
kono
parents:
diff changeset
2221
kono
parents:
diff changeset
2222 _M_deallocate_buckets();
kono
parents:
diff changeset
2223 _M_bucket_count = __n;
kono
parents:
diff changeset
2224 _M_buckets = __new_buckets;
kono
parents:
diff changeset
2225 }
kono
parents:
diff changeset
2226
kono
parents:
diff changeset
2227 #if __cplusplus > 201402L
kono
parents:
diff changeset
2228 template<typename, typename, typename> class _Hash_merge_helper { };
kono
parents:
diff changeset
2229 #endif // C++17
kono
parents:
diff changeset
2230
kono
parents:
diff changeset
2231 _GLIBCXX_END_NAMESPACE_VERSION
kono
parents:
diff changeset
2232 } // namespace std
kono
parents:
diff changeset
2233
kono
parents:
diff changeset
2234 #endif // _HASHTABLE_H