MongoDB C++ Driver  legacy-1.1.2
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 
22 namespace mongo {
23 template <typename K_L, typename K_S, typename V, typename H, typename E, typename C, typename C_LS>
24 inline 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 
30 template <typename K_L, typename K_S, typename V, typename H, typename E, typename C, typename C_LS>
31 inline 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 
38 template <typename K_L, typename K_S, typename V, typename H, typename E, typename C, typename C_LS>
39 inline 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 
74 template <typename K_L, typename K_S, typename V, typename H, typename E, typename C, typename C_LS>
75 inline 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  }
89 
90  newArea->_entries[firstEmpty] = _entries[i];
91  }
92  return true;
93 }
94 
95 template <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 
102 template <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 
113 template <typename K_L, typename K_S, typename V, typename H, typename E, typename C, typename C_LS>
114 inline 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 
122 template <typename K_L, typename K_S, typename V, typename H, typename E, typename C, typename C_LS>
123 inline 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 
149 template <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 
163 template <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 
173 template <typename K_L, typename K_S, typename V, typename H, typename E, typename C, typename C_LS>
174 inline 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 
189 template <typename K_L, typename K_S, typename V, typename H, typename E, typename C, typename C_LS>
190 inline 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);
198 }
199 
200 template <typename K_L, typename K_S, typename V, typename H, typename E, typename C, typename C_LS>
203  return const_iterator();
204 }
205 
206 template <typename K_L, typename K_S, typename V, typename H, typename E, typename C, typename C_LS>
207 inline typename UnorderedFastKeyTable<K_L, K_S, V, H, E, C, C_LS>::const_iterator
208 UnorderedFastKeyTable<K_L, K_S, V, H, E, C, C_LS>::begin() const {
209  return const_iterator(&_area);
210 }
211 }
Utility functions for parsing numbers from strings.
Definition: compare_numbers.h:20
size_t erase(const K_L &key)
Definition: unordered_fast_key_table_internal.h:150
Definition: unordered_fast_key_table.h:41
const_iterator find(const K_L &key) const
Definition: unordered_fast_key_table_internal.h:191
UnorderedFastKeyTable(unsigned startingCapacity=DEFAULT_STARTING_CAPACITY, double maxProbeRatio=0.05)
Definition: unordered_fast_key_table_internal.h:96
Definition: unordered_fast_key_table.h:130