summaryrefslogtreecommitdiff
path: root/src/mongo/db/concurrency/fast_map_noalloc.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/mongo/db/concurrency/fast_map_noalloc.h')
-rw-r--r--src/mongo/db/concurrency/fast_map_noalloc.h357
1 files changed, 171 insertions, 186 deletions
diff --git a/src/mongo/db/concurrency/fast_map_noalloc.h b/src/mongo/db/concurrency/fast_map_noalloc.h
index e7077a56222..cc2ccdb64ae 100644
--- a/src/mongo/db/concurrency/fast_map_noalloc.h
+++ b/src/mongo/db/concurrency/fast_map_noalloc.h
@@ -32,244 +32,229 @@
#include "mongo/util/assert_util.h"
namespace mongo {
-
+
+/**
+ * NOTE: This structure should not be used for anything other than the Lock Manager.
+ *
+ * This is a simple implementation of an unordered associative array with minimal
+ * functionality, used by the lock manager. It keeps a small number of memory entries to store
+ * values, in order to avoid memory allocations, which dominate the cost of the lock manager
+ * calls by a wide margin.
+ *
+ * This class is not thread-safe.
+ */
+template <class KeyType, class ValueType, int PreallocCount>
+class FastMapNoAlloc {
+public:
/**
- * NOTE: This structure should not be used for anything other than the Lock Manager.
- *
- * This is a simple implementation of an unordered associative array with minimal
- * functionality, used by the lock manager. It keeps a small number of memory entries to store
- * values, in order to avoid memory allocations, which dominate the cost of the lock manager
- * calls by a wide margin.
- *
- * This class is not thread-safe.
+ * Forward-only iterator. Does not synchronize with the underlying collection in any way.
+ * In other words, do not modify the collection while there is an open iterator on it.
*/
- template <class KeyType, class ValueType, int PreallocCount>
- class FastMapNoAlloc {
+ template <class MapType, class IteratorValueType>
+ class IteratorImpl {
public:
+ IteratorImpl(const IteratorImpl& other) : _map(other._map), _idx(other._idx) {}
- /**
- * Forward-only iterator. Does not synchronize with the underlying collection in any way.
- * In other words, do not modify the collection while there is an open iterator on it.
- */
- template<class MapType, class IteratorValueType>
- class IteratorImpl {
- public:
-
- IteratorImpl(const IteratorImpl& other)
- : _map(other._map),
- _idx(other._idx) {
-
- }
+ //
+ // Operators
+ //
- //
- // Operators
- //
+ bool operator!() const {
+ return finished();
+ }
- bool operator!() const {
- return finished();
- }
+ IteratorValueType& operator*() const {
+ return *objAddr();
+ }
- IteratorValueType& operator*() const {
- return *objAddr();
- }
+ IteratorValueType* operator->() const {
+ return objAddr();
+ }
- IteratorValueType* operator->() const {
- return objAddr();
- }
+ //
+ // Other methods
+ //
- //
- // Other methods
- //
+ /**
+ * Returns whether the iterator has been exhausted through calls to next. This value
+ * can be used to determine whether a previous call to find has found something.
+ */
+ bool finished() const {
+ return (MONGO_unlikely(_idx == PreallocCount));
+ }
- /**
- * Returns whether the iterator has been exhausted through calls to next. This value
- * can be used to determine whether a previous call to find has found something.
- */
- bool finished() const {
- return (MONGO_unlikely(_idx == PreallocCount));
- }
+ /**
+ * Returns the address of the object at the current position. Cannot be called with an
+ * uninitialized iterator, or iterator which has reached the end.
+ */
+ IteratorValueType* objAddr() const {
+ invariant(!finished());
- /**
- * Returns the address of the object at the current position. Cannot be called with an
- * uninitialized iterator, or iterator which has reached the end.
- */
- IteratorValueType* objAddr() const {
- invariant(!finished());
+ return &_map._fastAccess[_idx].value;
+ }
- return &_map._fastAccess[_idx].value;
- }
+ /**
+ * Returns the key of the value at the current position. Cannot be called with an
+ * uninitialized iterator or iterator which has reached the end.
+ */
+ const KeyType& key() const {
+ invariant(!finished());
- /**
- * Returns the key of the value at the current position. Cannot be called with an
- * uninitialized iterator or iterator which has reached the end.
- */
- const KeyType& key() const {
- invariant(!finished());
+ return _map._fastAccess[_idx].key;
+ }
- return _map._fastAccess[_idx].key;
- }
+ /**
+ * Advances the iterator to the next entry. No particular order of iteration is
+ * guaranteed.
+ */
+ void next() {
+ invariant(!finished());
- /**
- * Advances the iterator to the next entry. No particular order of iteration is
- * guaranteed.
- */
- void next() {
- invariant(!finished());
-
- while (++_idx < PreallocCount) {
- if (_map._fastAccess[_idx].inUse) {
- return;
- }
+ while (++_idx < PreallocCount) {
+ if (_map._fastAccess[_idx].inUse) {
+ return;
}
}
+ }
- /**
- * Removes the element at the current position and moves the iterator to the next,
- * which might be the last entry on the map.
- */
- void remove() {
- invariant(!finished());
- invariant(_map._fastAccess[_idx].inUse);
-
- _map._fastAccess[_idx].inUse = false;
- _map._fastAccessUsedSize--;
-
- next();
- }
-
-
- private:
-
- friend class FastMapNoAlloc<KeyType, ValueType, PreallocCount>;
+ /**
+ * Removes the element at the current position and moves the iterator to the next,
+ * which might be the last entry on the map.
+ */
+ void remove() {
+ invariant(!finished());
+ invariant(_map._fastAccess[_idx].inUse);
- // Used for iteration of the complete map
- IteratorImpl(MapType& map)
- : _map(map),
- _idx(-1) {
+ _map._fastAccess[_idx].inUse = false;
+ _map._fastAccessUsedSize--;
- next();
- }
+ next();
+ }
- // Used for iterator starting at a position
- IteratorImpl(MapType& map, int idx)
- : _map(map),
- _idx(idx) {
- invariant(_idx >= 0);
- }
+ private:
+ friend class FastMapNoAlloc<KeyType, ValueType, PreallocCount>;
- // Used for iteration starting at a particular key
- IteratorImpl(MapType& map, const KeyType& key)
- : _map(map),
- _idx(0) {
+ // Used for iteration of the complete map
+ IteratorImpl(MapType& map) : _map(map), _idx(-1) {
+ next();
+ }
- while (_idx < PreallocCount) {
- if (_map._fastAccess[_idx].inUse && (_map._fastAccess[_idx].key == key)) {
- return;
- }
+ // Used for iterator starting at a position
+ IteratorImpl(MapType& map, int idx) : _map(map), _idx(idx) {
+ invariant(_idx >= 0);
+ }
- ++_idx;
+ // Used for iteration starting at a particular key
+ IteratorImpl(MapType& map, const KeyType& key) : _map(map), _idx(0) {
+ while (_idx < PreallocCount) {
+ if (_map._fastAccess[_idx].inUse && (_map._fastAccess[_idx].key == key)) {
+ return;
}
- }
+ ++_idx;
+ }
+ }
- // The map being iterated on
- MapType& _map;
-
- // Index to the current entry being iterated
- int _idx;
- };
+ // The map being iterated on
+ MapType& _map;
- typedef IteratorImpl<FastMapNoAlloc<KeyType, ValueType, PreallocCount>,
- ValueType> Iterator;
+ // Index to the current entry being iterated
+ int _idx;
+ };
- typedef IteratorImpl<const FastMapNoAlloc<KeyType, ValueType, PreallocCount>,
- const ValueType> ConstIterator;
+ typedef IteratorImpl<FastMapNoAlloc<KeyType, ValueType, PreallocCount>, ValueType> Iterator;
- FastMapNoAlloc() : _fastAccess(),
- _fastAccessUsedSize(0) { }
+ typedef IteratorImpl<const FastMapNoAlloc<KeyType, ValueType, PreallocCount>, const ValueType>
+ ConstIterator;
- /**
- * Inserts the specified entry in the map and returns a reference to the memory for the
- * entry just inserted.
- */
- Iterator insert(const KeyType& key) {
- // Find the first unused slot. This could probably be even further optimized by adding
- // a field pointing to the first unused location.
- int idx = 0;
- for (; _fastAccess[idx].inUse; idx++);
- invariant(idx < PreallocCount);
+ FastMapNoAlloc() : _fastAccess(), _fastAccessUsedSize(0) {}
- _fastAccess[idx].inUse = true;
- _fastAccess[idx].key = key;
- _fastAccessUsedSize++;
+ /**
+ * Inserts the specified entry in the map and returns a reference to the memory for the
+ * entry just inserted.
+ */
+ Iterator insert(const KeyType& key) {
+ // Find the first unused slot. This could probably be even further optimized by adding
+ // a field pointing to the first unused location.
+ int idx = 0;
+ for (; _fastAccess[idx].inUse; idx++)
+ ;
- return Iterator(*this, idx);
- }
+ invariant(idx < PreallocCount);
- /**
- * Returns an iterator to the first element in the map.
- */
- Iterator begin() {
- return Iterator(*this);
- }
+ _fastAccess[idx].inUse = true;
+ _fastAccess[idx].key = key;
+ _fastAccessUsedSize++;
- ConstIterator begin() const {
- return ConstIterator(*this);
- }
+ return Iterator(*this, idx);
+ }
- /**
- * Returns an iterator pointing to the first position, which has entry with the specified
- * key. Before dereferencing the returned iterator, it should be checked for validity using
- * the finished() method or the ! operator. If no element was found, finished() will return
- * false.
- *
- * While it is allowed to call next() on the returned iterator, this is not very useful,
- * because the container is not ordered.
- */
- Iterator find(const KeyType& key) {
- return Iterator(*this, key);
- }
+ /**
+ * Returns an iterator to the first element in the map.
+ */
+ Iterator begin() {
+ return Iterator(*this);
+ }
- ConstIterator find(const KeyType& key) const {
- return ConstIterator(*this, key);
- }
+ ConstIterator begin() const {
+ return ConstIterator(*this);
+ }
- int size() const { return _fastAccessUsedSize; }
- bool empty() const { return (_fastAccessUsedSize == 0); }
+ /**
+ * Returns an iterator pointing to the first position, which has entry with the specified
+ * key. Before dereferencing the returned iterator, it should be checked for validity using
+ * the finished() method or the ! operator. If no element was found, finished() will return
+ * false.
+ *
+ * While it is allowed to call next() on the returned iterator, this is not very useful,
+ * because the container is not ordered.
+ */
+ Iterator find(const KeyType& key) {
+ return Iterator(*this, key);
+ }
- private:
+ ConstIterator find(const KeyType& key) const {
+ return ConstIterator(*this, key);
+ }
- // Empty and very large maps do not make sense since there will be no performance gain, so
- // disallow them.
- BOOST_STATIC_ASSERT(PreallocCount > 0);
- BOOST_STATIC_ASSERT(PreallocCount < 32);
+ int size() const {
+ return _fastAccessUsedSize;
+ }
+ bool empty() const {
+ return (_fastAccessUsedSize == 0);
+ }
- // Iterator accesses the map directly
- friend class IteratorImpl<FastMapNoAlloc<KeyType, ValueType, PreallocCount>,
- ValueType>;
+private:
+ // Empty and very large maps do not make sense since there will be no performance gain, so
+ // disallow them.
+ BOOST_STATIC_ASSERT(PreallocCount > 0);
+ BOOST_STATIC_ASSERT(PreallocCount < 32);
- friend class IteratorImpl<const FastMapNoAlloc<KeyType, ValueType, PreallocCount>,
- const ValueType>;
+ // Iterator accesses the map directly
+ friend class IteratorImpl<FastMapNoAlloc<KeyType, ValueType, PreallocCount>, ValueType>;
+ friend class IteratorImpl<const FastMapNoAlloc<KeyType, ValueType, PreallocCount>,
+ const ValueType>;
- struct PreallocEntry {
- PreallocEntry() : inUse(false) { }
- bool inUse;
+ struct PreallocEntry {
+ PreallocEntry() : inUse(false) {}
- KeyType key;
- ValueType value;
- };
+ bool inUse;
- // Pre-allocated memory for entries
- PreallocEntry _fastAccess[PreallocCount];
- int _fastAccessUsedSize;
+ KeyType key;
+ ValueType value;
};
-} // namespace mongo
+ // Pre-allocated memory for entries
+ PreallocEntry _fastAccess[PreallocCount];
+ int _fastAccessUsedSize;
+};
+
+} // namespace mongo