LRUStrategy.h 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  1. //
  2. // LRUStrategy.h
  3. //
  4. // $Id: //poco/1.4/Foundation/include/Poco/LRUStrategy.h#1 $
  5. //
  6. // Library: Foundation
  7. // Package: Cache
  8. // Module: LRUStrategy
  9. //
  10. // Definition of the LRUStrategy class.
  11. //
  12. // Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
  13. // and Contributors.
  14. //
  15. // SPDX-License-Identifier: BSL-1.0
  16. //
  17. #ifndef Foundation_LRUStrategy_INCLUDED
  18. #define Foundation_LRUStrategy_INCLUDED
  19. #include "Poco/KeyValueArgs.h"
  20. #include "Poco/ValidArgs.h"
  21. #include "Poco/AbstractStrategy.h"
  22. #include "Poco/EventArgs.h"
  23. #include "Poco/Exception.h"
  24. #include <list>
  25. #include <map>
  26. #include <cstddef>
  27. namespace Poco {
  28. template <class TKey, class TValue>
  29. class LRUStrategy: public AbstractStrategy<TKey, TValue>
  30. /// An LRUStrategy implements least recently used cache replacement.
  31. {
  32. public:
  33. typedef std::list<TKey> Keys;
  34. typedef typename Keys::iterator Iterator;
  35. typedef typename Keys::const_iterator ConstIterator;
  36. typedef std::map<TKey, Iterator> KeyIndex;
  37. typedef typename KeyIndex::iterator IndexIterator;
  38. typedef typename KeyIndex::const_iterator ConstIndexIterator;
  39. public:
  40. LRUStrategy(std::size_t size):
  41. _size(size)
  42. {
  43. if (_size < 1) throw InvalidArgumentException("size must be > 0");
  44. }
  45. ~LRUStrategy()
  46. {
  47. }
  48. void onAdd(const void*, const KeyValueArgs <TKey, TValue>& args)
  49. {
  50. _keys.push_front(args.key());
  51. std::pair<IndexIterator, bool> stat = _keyIndex.insert(std::make_pair(args.key(), _keys.begin()));
  52. if (!stat.second)
  53. {
  54. stat.first->second = _keys.begin();
  55. }
  56. }
  57. void onRemove(const void*, const TKey& key)
  58. {
  59. IndexIterator it = _keyIndex.find(key);
  60. if (it != _keyIndex.end())
  61. {
  62. _keys.erase(it->second);
  63. _keyIndex.erase(it);
  64. }
  65. }
  66. void onGet(const void*, const TKey& key)
  67. {
  68. // LRU: in case of an hit, move to begin
  69. IndexIterator it = _keyIndex.find(key);
  70. if (it != _keyIndex.end())
  71. {
  72. _keys.splice(_keys.begin(), _keys, it->second); //_keys.erase(it->second)+_keys.push_front(key);
  73. it->second = _keys.begin();
  74. }
  75. }
  76. void onClear(const void*, const EventArgs& args)
  77. {
  78. _keys.clear();
  79. _keyIndex.clear();
  80. }
  81. void onIsValid(const void*, ValidArgs<TKey>& args)
  82. {
  83. if (_keyIndex.find(args.key()) == _keyIndex.end())
  84. {
  85. args.invalidate();
  86. }
  87. }
  88. void onReplace(const void*, std::set<TKey>& elemsToRemove)
  89. {
  90. // Note: replace only informs the cache which elements
  91. // it would like to remove!
  92. // it does not remove them on its own!
  93. std::size_t curSize = _keyIndex.size();
  94. if (curSize < _size)
  95. {
  96. return;
  97. }
  98. std::size_t diff = curSize - _size;
  99. Iterator it = --_keys.end(); //--keys can never be invoked on an empty list due to the minSize==1 requirement of LRU
  100. std::size_t i = 0;
  101. while (i++ < diff)
  102. {
  103. elemsToRemove.insert(*it);
  104. if (it != _keys.begin())
  105. {
  106. --it;
  107. }
  108. }
  109. }
  110. protected:
  111. std::size_t _size; /// Number of keys the cache can store.
  112. Keys _keys;
  113. KeyIndex _keyIndex; /// For faster access to _keys
  114. };
  115. } // namespace Poco
  116. #endif // Foundation_LRUStrategy_INCLUDED