UniqueAccessExpireStrategy.h 3.9 KB

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