MongoDB C++ Driver legacy-1.0.0
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 {
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
31 template< typename K_L, typename K_S, typename V, typename H, typename E, typename C, typename C_LS >
32 inline UnorderedFastKeyTable<K_L, K_S, V, H, E, C, C_LS>::Area::Area(const Area& other )
33 : _capacity( other._capacity ),
34 _maxProbe( other._maxProbe ),
35 _entries( new Entry[_capacity] ) {
36 for ( unsigned i = 0; i < _capacity; i++ ) {
37 _entries[i] = other._entries[i];
38 }
39 }
40
41 template< typename K_L, typename K_S, typename V, typename H, typename E, typename C, typename C_LS >
42 inline int UnorderedFastKeyTable<K_L, K_S, V, H, E, C, C_LS>::Area::find(
43 const K_L& key,
44 size_t hash,
45 int* firstEmpty,
46 const UnorderedFastKeyTable& sm ) const {
47 if ( firstEmpty )
48 *firstEmpty = -1;
49
50 for ( unsigned probe = 0; probe < _maxProbe; probe++ ) {
51 unsigned pos = (hash + probe) % _capacity;
52
53 if ( ! _entries[pos].used ) {
54 // space is empty
55 if ( firstEmpty && *firstEmpty == -1 )
56 *firstEmpty = pos;
57 if ( ! _entries[pos].everUsed )
58 return -1;
59 continue;
60 }
61
62 if ( _entries[pos].curHash != hash ) {
63 // space has something else
64 continue;
65 }
66
67 if ( ! sm._equals(key, sm._convertor( _entries[pos].data.first ) ) ) {
68 // hashes match
69 // strings are not equals
70 continue;
71 }
72
73 // hashes and strings are equal
74 // yay!
75 return pos;
76 }
77 return -1;
78 }
79
80 template< typename K_L, typename K_S, typename V, typename H, typename E, typename C, typename C_LS >
81 inline bool UnorderedFastKeyTable<K_L, K_S, V, H, E, C, C_LS>::Area::transfer(
82 Area* newArea,
83 const UnorderedFastKeyTable& sm) const {
84 for ( unsigned i = 0; i < _capacity; i++ ) {
85 if ( ! _entries[i].used )
86 continue;
87
88 int firstEmpty = -1;
89 int loc = newArea->find( sm._convertor( _entries[i].data.first ),
90 _entries[i].curHash,
91 &firstEmpty,
92 sm );
93
94 verify( loc == -1 );
95 if ( firstEmpty < 0 ) {
96 return false;
97 }
98
99 newArea->_entries[firstEmpty] = _entries[i];
100 }
101 return true;
102 }
103
104 template< typename K_L, typename K_S, typename V, typename H, typename E, typename C, typename C_LS >
106 unsigned startingCapacity,
107 double maxProbeRatio)
108 : _maxProbeRatio( maxProbeRatio ), _area( startingCapacity, maxProbeRatio ) {
109 _size = 0;
110 }
111
112 template< typename K_L, typename K_S, typename V, typename H, typename E, typename C, typename C_LS >
114 const UnorderedFastKeyTable& other )
115 : _size( other._size ),
116 _maxProbeRatio( other._maxProbeRatio ),
117 _area( other._area ),
118 _hash( other._hash ),
119 _equals( other._equals ),
120 _convertor( other._convertor ),
121 _convertorOther( other._convertorOther ) {
122 }
123
124 template< typename K_L, typename K_S, typename V, typename H, typename E, typename C, typename C_LS >
126 out->_size = _size;
127 out->_maxProbeRatio = _maxProbeRatio;
128 Area x( _area );
129 out->_area.swap( &x );
130 }
131
132 template< typename K_L, typename K_S, typename V, typename H, typename E, typename C, typename C_LS >
133 inline V& UnorderedFastKeyTable<K_L, K_S, V, H, E, C, C_LS>::get( const K_L& key ) {
134
135 const size_t hash = _hash( key );
136
137 for ( int numGrowTries = 0; numGrowTries < 5; numGrowTries++ ) {
138 int firstEmpty = -1;
139 int pos = _area.find( key, hash, &firstEmpty, *this );
140 if ( pos >= 0 )
141 return _area._entries[pos].data.second;
142
143 // key not in map
144 // need to add
145 if ( firstEmpty >= 0 ) {
146 _size++;
147 _area._entries[firstEmpty].used = true;
148 _area._entries[firstEmpty].everUsed = true;
149 _area._entries[firstEmpty].curHash = hash;
150 _area._entries[firstEmpty].data.first = _convertorOther(key);
151 return _area._entries[firstEmpty].data.second;
152 }
153
154 // no space left in map
155 _grow();
156 }
157 msgasserted( 16471, "UnorderedFastKeyTable couldn't add entry after growing many times" );
158 }
159
160 template< typename K_L, typename K_S, typename V, typename H, typename E, typename C, typename C_LS >
162
163 const size_t hash = _hash( key );
164 int pos = _area.find( key, hash, NULL, *this );
165
166 if ( pos < 0 )
167 return 0;
168
169 --_size;
170 _area._entries[pos].used = false;
171 _area._entries[pos].data.second = V();
172 return 1;
173 }
174
175 template< typename K_L, typename K_S, typename V, typename H, typename E, typename C, typename C_LS >
177 dassert(it._position >= 0);
178 dassert(it._area == &_area);
179
180 --_size;
181 _area._entries[it._position].used = false;
182 _area._entries[it._position].data.second = V();
183 }
185 template< typename K_L, typename K_S, typename V, typename H, typename E, typename C, typename C_LS >
187 unsigned capacity = _area._capacity;
188 for ( int numGrowTries = 0; numGrowTries < 5; numGrowTries++ ) {
189 capacity *= 2;
190 Area newArea( capacity, _maxProbeRatio );
191 bool success = _area.transfer( &newArea, *this );
192 if ( !success ) {
193 continue;
194 }
195 _area.swap( &newArea );
196 return;
197 }
198 msgasserted( 16845,
199 "UnorderedFastKeyTable::_grow couldn't add entry after growing many times" );
200 }
201
202 template< typename K_L, typename K_S, typename V, typename H, typename E, typename C, typename C_LS >
205 if ( _size == 0 )
206 return const_iterator();
207 int pos = _area.find( key, _hash(key), 0, *this );
208 if ( pos < 0 )
209 return const_iterator();
210 return const_iterator( &_area, pos );
211 }
212
213 template< typename K_L, typename K_S, typename V, typename H, typename E, typename C, typename C_LS >
216 return const_iterator();
217 }
218
219 template< typename K_L, typename K_S, typename V, typename H, typename E, typename C, typename C_LS >
220 inline typename UnorderedFastKeyTable<K_L, K_S, V, H, E, C, C_LS>::const_iterator
221 UnorderedFastKeyTable<K_L, K_S, V, H, E, C, C_LS>::begin() const {
222 return const_iterator( &_area );
223 }
224}
Definition unordered_fast_key_table.h:121
Definition unordered_fast_key_table.h:41
UnorderedFastKeyTable(unsigned startingCapacity=DEFAULT_STARTING_CAPACITY, double maxProbeRatio=0.05)
Definition unordered_fast_key_table_internal.h:105
const_iterator find(const K_L &key) const
Definition unordered_fast_key_table_internal.h:204
size_t erase(const K_L &key)
Definition unordered_fast_key_table_internal.h:161
the main MongoDB namespace
Definition bulk_operation_builder.h:24