You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

limitedmap.h 3.2KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  1. // Copyright (c) 2012-2015 The Bitcoin Core developers
  2. // Distributed under the MIT software license, see the accompanying
  3. // file COPYING or http://www.opensource.org/licenses/mit-license.php.
  4. #ifndef BITCOIN_LIMITEDMAP_H
  5. #define BITCOIN_LIMITEDMAP_H
  6. #include <assert.h>
  7. #include <map>
  8. /** STL-like map container that only keeps the N elements with the highest value. */
  9. template <typename K, typename V>
  10. class limitedmap
  11. {
  12. public:
  13. typedef K key_type;
  14. typedef V mapped_type;
  15. typedef std::pair<const key_type, mapped_type> value_type;
  16. typedef typename std::map<K, V>::const_iterator const_iterator;
  17. typedef typename std::map<K, V>::size_type size_type;
  18. protected:
  19. std::map<K, V> map;
  20. typedef typename std::map<K, V>::iterator iterator;
  21. std::multimap<V, iterator> rmap;
  22. typedef typename std::multimap<V, iterator>::iterator rmap_iterator;
  23. size_type nMaxSize;
  24. public:
  25. limitedmap(size_type nMaxSizeIn)
  26. {
  27. assert(nMaxSizeIn > 0);
  28. nMaxSize = nMaxSizeIn;
  29. }
  30. const_iterator begin() const { return map.begin(); }
  31. const_iterator end() const { return map.end(); }
  32. size_type size() const { return map.size(); }
  33. bool empty() const { return map.empty(); }
  34. const_iterator find(const key_type& k) const { return map.find(k); }
  35. size_type count(const key_type& k) const { return map.count(k); }
  36. void insert(const value_type& x)
  37. {
  38. std::pair<iterator, bool> ret = map.insert(x);
  39. if (ret.second) {
  40. if (map.size() > nMaxSize) {
  41. map.erase(rmap.begin()->second);
  42. rmap.erase(rmap.begin());
  43. }
  44. rmap.insert(make_pair(x.second, ret.first));
  45. }
  46. }
  47. void erase(const key_type& k)
  48. {
  49. iterator itTarget = map.find(k);
  50. if (itTarget == map.end())
  51. return;
  52. std::pair<rmap_iterator, rmap_iterator> itPair = rmap.equal_range(itTarget->second);
  53. for (rmap_iterator it = itPair.first; it != itPair.second; ++it)
  54. if (it->second == itTarget) {
  55. rmap.erase(it);
  56. map.erase(itTarget);
  57. return;
  58. }
  59. // Shouldn't ever get here
  60. assert(0);
  61. }
  62. void update(const_iterator itIn, const mapped_type& v)
  63. {
  64. // TODO: When we switch to C++11, use map.erase(itIn, itIn) to get the non-const iterator.
  65. iterator itTarget = map.find(itIn->first);
  66. if (itTarget == map.end())
  67. return;
  68. std::pair<rmap_iterator, rmap_iterator> itPair = rmap.equal_range(itTarget->second);
  69. for (rmap_iterator it = itPair.first; it != itPair.second; ++it)
  70. if (it->second == itTarget) {
  71. rmap.erase(it);
  72. itTarget->second = v;
  73. rmap.insert(make_pair(v, itTarget));
  74. return;
  75. }
  76. // Shouldn't ever get here
  77. assert(0);
  78. }
  79. size_type max_size() const { return nMaxSize; }
  80. size_type max_size(size_type s)
  81. {
  82. assert(s > 0);
  83. while (map.size() > s) {
  84. map.erase(rmap.begin()->second);
  85. rmap.erase(rmap.begin());
  86. }
  87. nMaxSize = s;
  88. return nMaxSize;
  89. }
  90. };
  91. #endif // BITCOIN_LIMITEDMAP_H