UniqueAccessExpireStrategy.h 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  1. //
  2. // UniqueAccessExpireStrategy.h
  3. //
  4. // Library: Foundation
  5. // Package: Cache
  6. // Module: UniqueAccessExpireStrategy
  7. //
  8. // Definition of the UniqueAccessExpireStrategy class.
  9. //
  10. // Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
  11. // and Contributors.
  12. //
  13. // SPDX-License-Identifier: BSL-1.0
  14. //
  15. #ifndef Foundation_UniqueAccessExpireStrategy_INCLUDED
  16. #define Foundation_UniqueAccessExpireStrategy_INCLUDED
  17. #include "Poco/KeyValueArgs.h"
  18. #include "Poco/ValidArgs.h"
  19. #include "Poco/AbstractStrategy.h"
  20. #include "Poco/Bugcheck.h"
  21. #include "Poco/Timestamp.h"
  22. #include "Poco/Timespan.h"
  23. #include "Poco/EventArgs.h"
  24. #include "Poco/UniqueExpireStrategy.h"
  25. #include <set>
  26. #include <map>
  27. namespace Poco {
  28. template <
  29. class TKey,
  30. class TValue
  31. >
  32. class UniqueAccessExpireStrategy: public AbstractStrategy<TKey, TValue>
  33. /// An UniqueExpireStrategy implements time based expiration of cache entries. In contrast
  34. /// to ExpireStrategy which only allows to set a per cache expiration value, it allows to define
  35. /// expiration per CacheEntry.
  36. /// Each TValue object must thus offer the following method:
  37. ///
  38. /// const Poco::Timestamp& getTimeout() const;
  39. ///
  40. /// which returns the timespan for how long an object will be valid without being accessed.
  41. {
  42. public:
  43. typedef std::pair<TKey, Timespan> KeyExpire;
  44. typedef std::multimap<Timestamp, KeyExpire> TimeIndex;
  45. typedef typename TimeIndex::iterator IndexIterator;
  46. typedef typename TimeIndex::const_iterator ConstIndexIterator;
  47. typedef std::map<TKey, IndexIterator> Keys;
  48. typedef typename Keys::iterator Iterator;
  49. public:
  50. UniqueAccessExpireStrategy()
  51. /// Create an unique expire strategy.
  52. {
  53. }
  54. ~UniqueAccessExpireStrategy()
  55. {
  56. }
  57. void onAdd(const void*, const KeyValueArgs <TKey, TValue>& args)
  58. {
  59. // the expire value defines how many millisecs in the future the
  60. // value will expire, even insert negative values!
  61. Timestamp expire;
  62. expire += args.value().getTimeout().totalMicroseconds();
  63. IndexIterator it = _keyIndex.insert(std::make_pair(expire, std::make_pair(args.key(), args.value().getTimeout())));
  64. std::pair<Iterator, bool> stat = _keys.insert(std::make_pair(args.key(), it));
  65. if (!stat.second)
  66. {
  67. _keyIndex.erase(stat.first->second);
  68. stat.first->second = it;
  69. }
  70. }
  71. void onRemove(const void*, const TKey& key)
  72. {
  73. Iterator it = _keys.find(key);
  74. if (it != _keys.end())
  75. {
  76. _keyIndex.erase(it->second);
  77. _keys.erase(it);
  78. }
  79. }
  80. void onGet(const void*, const TKey& key)
  81. {
  82. // get updates the expiration time stamp
  83. Iterator it = _keys.find(key);
  84. if (it != _keys.end())
  85. {
  86. KeyExpire ke = it->second->second;
  87. // gen new absolute expire value
  88. Timestamp expire;
  89. expire += ke.second.totalMicroseconds();
  90. // delete old index
  91. _keyIndex.erase(it->second);
  92. IndexIterator itt = _keyIndex.insert(std::make_pair(expire, ke));
  93. // update iterator
  94. it->second = itt;
  95. }
  96. }
  97. void onClear(const void*, const EventArgs& args)
  98. {
  99. _keys.clear();
  100. _keyIndex.clear();
  101. }
  102. void onIsValid(const void*, ValidArgs<TKey>& args)
  103. {
  104. Iterator it = _keys.find(args.key());
  105. if (it != _keys.end())
  106. {
  107. Timestamp now;
  108. if (it->second->first <= now)
  109. {
  110. args.invalidate();
  111. }
  112. }
  113. else //not found: probably removed by onReplace
  114. args.invalidate();
  115. }
  116. void onReplace(const void*, std::set<TKey>& elemsToRemove)
  117. {
  118. // Note: replace only informs the cache which elements
  119. // it would like to remove!
  120. // it does not remove them on its own!
  121. IndexIterator it = _keyIndex.begin();
  122. Timestamp now;
  123. while (it != _keyIndex.end() && it->first < now)
  124. {
  125. elemsToRemove.insert(it->second.first);
  126. ++it;
  127. }
  128. }
  129. protected:
  130. Keys _keys; /// For faster replacement of keys, the iterator points to the _keyIndex map
  131. TimeIndex _keyIndex; /// Maps time to key value
  132. };
  133. } // namespace Poco
  134. #endif // Foundation_UniqueAccessExpireStrategy_INCLUDED