MongoDB C++ Driver  legacy-1.0.5
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
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 
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 >
125  inline void UnorderedFastKeyTable<K_L, K_S, V, H, E, C, C_LS>::copyTo( UnorderedFastKeyTable* out ) const {
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  }
184 
185  template< typename K_L, typename K_S, typename V, typename H, typename E, typename C, typename C_LS >
186  inline void UnorderedFastKeyTable<K_L, K_S, V, H, E, C, C_LS>::_grow() {
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 >
203  inline typename UnorderedFastKeyTable<K_L, K_S, V, H, E, C, C_LS>::const_iterator
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 }
the main MongoDB namespace
Definition: bulk_operation_builder.h:24
size_t erase(const K_L &key)
Definition: unordered_fast_key_table_internal.h:161
Definition: unordered_fast_key_table.h:41
const_iterator find(const K_L &key) const
Definition: unordered_fast_key_table_internal.h:204
UnorderedFastKeyTable(unsigned startingCapacity=DEFAULT_STARTING_CAPACITY, double maxProbeRatio=0.05)
Definition: unordered_fast_key_table_internal.h:105
Definition: unordered_fast_key_table.h:121