MongoDB C++ Driver legacy-1.1.2
Loading...
Searching...
No Matches
unordered_fast_key_table_internal.h
1// unordered_fast_key_table_internal.h
2
3
4/* Copyright 2012 10gen Inc.
5 *
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 */
18
19#include "mongo/util/assert_util.h"
20#include "mongo/util/debug_util.h"
21
22namespace mongo {
23template <typename K_L, typename K_S, typename V, typename H, typename E, typename C, typename C_LS>
24inline UnorderedFastKeyTable<K_L, K_S, V, H, E, C, C_LS>::Area::Area(unsigned capacity,
25 double maxProbeRatio)
26 : _capacity(capacity),
27 _maxProbe(static_cast<unsigned>(capacity * maxProbeRatio)),
28 _entries(new Entry[_capacity]) {}
29
30template <typename K_L, typename K_S, typename V, typename H, typename E, typename C, typename C_LS>
31inline UnorderedFastKeyTable<K_L, K_S, V, H, E, C, C_LS>::Area::Area(const Area& other)
32 : _capacity(other._capacity), _maxProbe(other._maxProbe), _entries(new Entry[_capacity]) {
33 for (unsigned i = 0; i < _capacity; i++) {
34 _entries[i] = other._entries[i];
35 }
36}
37
38template <typename K_L, typename K_S, typename V, typename H, typename E, typename C, typename C_LS>
39inline int UnorderedFastKeyTable<K_L, K_S, V, H, E, C, C_LS>::Area::find(
40 const K_L& key, size_t hash, int* firstEmpty, const UnorderedFastKeyTable& sm) const {
41 if (firstEmpty)
42 *firstEmpty = -1;
43
44 for (unsigned probe = 0; probe < _maxProbe; probe++) {
45 unsigned pos = (hash + probe) % _capacity;
46
47 if (!_entries[pos].used) {
48 // space is empty
49 if (firstEmpty && *firstEmpty == -1)
50 *firstEmpty = pos;
51 if (!_entries[pos].everUsed)
52 return -1;
53 continue;
54 }
55
56 if (_entries[pos].curHash != hash) {
57 // space has something else
58 continue;
59 }
60
61 if (!sm._equals(key, sm._convertor(_entries[pos].data.first))) {
62 // hashes match
63 // strings are not equals
64 continue;
65 }
66
67 // hashes and strings are equal
68 // yay!
69 return pos;
70 }
71 return -1;
72}
73
74template <typename K_L, typename K_S, typename V, typename H, typename E, typename C, typename C_LS>
75inline bool UnorderedFastKeyTable<K_L, K_S, V, H, E, C, C_LS>::Area::transfer(
76 Area* newArea, const UnorderedFastKeyTable& sm) const {
77 for (unsigned i = 0; i < _capacity; i++) {
78 if (!_entries[i].used)
79 continue;
80
81 int firstEmpty = -1;
82 int loc = newArea->find(
83 sm._convertor(_entries[i].data.first), _entries[i].curHash, &firstEmpty, sm);
84
85 verify(loc == -1);
86 if (firstEmpty < 0) {
87 return false;
88 }
90 newArea->_entries[firstEmpty] = _entries[i];
91 }
92 return true;
93}
94
95template <typename K_L, typename K_S, typename V, typename H, typename E, typename C, typename C_LS>
97 unsigned startingCapacity, double maxProbeRatio)
98 : _maxProbeRatio(maxProbeRatio), _area(startingCapacity, maxProbeRatio) {
99 _size = 0;
100}
101
102template <typename K_L, typename K_S, typename V, typename H, typename E, typename C, typename C_LS>
104 const UnorderedFastKeyTable& other)
105 : _size(other._size),
106 _maxProbeRatio(other._maxProbeRatio),
107 _area(other._area),
108 _hash(other._hash),
109 _equals(other._equals),
110 _convertor(other._convertor),
111 _convertorOther(other._convertorOther) {}
112
113template <typename K_L, typename K_S, typename V, typename H, typename E, typename C, typename C_LS>
114inline void UnorderedFastKeyTable<K_L, K_S, V, H, E, C, C_LS>::copyTo(
115 UnorderedFastKeyTable* out) const {
116 out->_size = _size;
117 out->_maxProbeRatio = _maxProbeRatio;
118 Area x(_area);
119 out->_area.swap(&x);
120}
121
122template <typename K_L, typename K_S, typename V, typename H, typename E, typename C, typename C_LS>
123inline V& UnorderedFastKeyTable<K_L, K_S, V, H, E, C, C_LS>::get(const K_L& key) {
124 const size_t hash = _hash(key);
125
126 for (int numGrowTries = 0; numGrowTries < 5; numGrowTries++) {
127 int firstEmpty = -1;
128 int pos = _area.find(key, hash, &firstEmpty, *this);
129 if (pos >= 0)
130 return _area._entries[pos].data.second;
131
132 // key not in map
133 // need to add
134 if (firstEmpty >= 0) {
135 _size++;
136 _area._entries[firstEmpty].used = true;
137 _area._entries[firstEmpty].everUsed = true;
138 _area._entries[firstEmpty].curHash = hash;
139 _area._entries[firstEmpty].data.first = _convertorOther(key);
140 return _area._entries[firstEmpty].data.second;
141 }
142
143 // no space left in map
144 _grow();
145 }
146 msgasserted(16471, "UnorderedFastKeyTable couldn't add entry after growing many times");
147}
148
149template <typename K_L, typename K_S, typename V, typename H, typename E, typename C, typename C_LS>
151 const size_t hash = _hash(key);
152 int pos = _area.find(key, hash, NULL, *this);
153
154 if (pos < 0)
155 return 0;
156
157 --_size;
158 _area._entries[pos].used = false;
159 _area._entries[pos].data.second = V();
160 return 1;
161}
162
163template <typename K_L, typename K_S, typename V, typename H, typename E, typename C, typename C_LS>
165 dassert(it._position >= 0);
166 dassert(it._area == &_area);
167
168 --_size;
169 _area._entries[it._position].used = false;
170 _area._entries[it._position].data.second = V();
171}
172
173template <typename K_L, typename K_S, typename V, typename H, typename E, typename C, typename C_LS>
174inline void UnorderedFastKeyTable<K_L, K_S, V, H, E, C, C_LS>::_grow() {
175 unsigned capacity = _area._capacity;
176 for (int numGrowTries = 0; numGrowTries < 5; numGrowTries++) {
177 capacity *= 2;
178 Area newArea(capacity, _maxProbeRatio);
179 bool success = _area.transfer(&newArea, *this);
180 if (!success) {
181 continue;
182 }
183 _area.swap(&newArea);
184 return;
185 }
186 msgasserted(16845, "UnorderedFastKeyTable::_grow couldn't add entry after growing many times");
187}
188
189template <typename K_L, typename K_S, typename V, typename H, typename E, typename C, typename C_LS>
190inline typename UnorderedFastKeyTable<K_L, K_S, V, H, E, C, C_LS>::const_iterator
192 if (_size == 0)
193 return const_iterator();
194 int pos = _area.find(key, _hash(key), 0, *this);
195 if (pos < 0)
196 return const_iterator();
197 return const_iterator(&_area, pos);
199
200template <typename K_L, typename K_S, typename V, typename H, typename E, typename C, typename C_LS>
203 return const_iterator();
204}
205
206template <typename K_L, typename K_S, typename V, typename H, typename E, typename C, typename C_LS>
207inline typename UnorderedFastKeyTable<K_L, K_S, V, H, E, C, C_LS>::const_iterator
208UnorderedFastKeyTable<K_L, K_S, V, H, E, C, C_LS>::begin() const {
209 return const_iterator(&_area);
210}
211}
Definition unordered_fast_key_table.h:130
Definition unordered_fast_key_table.h:41
UnorderedFastKeyTable(unsigned startingCapacity=DEFAULT_STARTING_CAPACITY, double maxProbeRatio=0.05)
Definition unordered_fast_key_table_internal.h:96
const_iterator find(const K_L &key) const
Definition unordered_fast_key_table_internal.h:191
size_t erase(const K_L &key)
Definition unordered_fast_key_table_internal.h:150
Utility functions for parsing numbers from strings.
Definition compare_numbers.h:20