cache.h 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767
  1. #pragma once
  2. #include <util/generic/algorithm.h>
  3. #include <util/generic/ptr.h>
  4. #include <util/generic/intrlist.h>
  5. #include <util/generic/hash_set.h>
  6. #include <util/generic/vector.h>
  7. #include <util/generic/yexception.h>
  8. #include <utility>
  9. template <class TValue>
  10. struct TUniformSizeProvider {
  11. size_t operator()(const TValue&) {
  12. return 1;
  13. }
  14. };
  15. template <typename TKey, typename TValue, class TSizeProvider = TUniformSizeProvider<TValue>>
  16. class TLRUList {
  17. public:
  18. TLRUList(size_t maxSize, const TSizeProvider& sizeProvider = TSizeProvider())
  19. : List()
  20. , SizeProvider(sizeProvider)
  21. , ItemsAmount(0)
  22. , TotalSize(0)
  23. , MaxSize(maxSize)
  24. {
  25. }
  26. public:
  27. struct TItem: public TIntrusiveListItem<TItem> {
  28. typedef TIntrusiveListItem<TItem> TBase;
  29. // universal reference for TKey here prevents TItem(/*non-const*/ TItem&) from compiling,
  30. // so explicitly specify const TKey& and TKey&&
  31. explicit TItem(const TKey& key)
  32. : TBase()
  33. , Key(key)
  34. , Value()
  35. {
  36. }
  37. explicit TItem(TKey&& key)
  38. : TBase()
  39. , Key(std::move(key))
  40. , Value()
  41. {
  42. }
  43. template<typename TKeyRef, typename TValueRef>
  44. TItem(TKeyRef&& key, TValueRef&& value)
  45. : TBase()
  46. , Key(std::forward<TKeyRef>(key))
  47. , Value(std::forward<TValueRef>(value))
  48. {
  49. }
  50. TItem(const TItem&) = default;
  51. TItem(TItem&&) = default;
  52. bool operator<(const TItem& rhs) const {
  53. return Key < rhs.Key;
  54. }
  55. bool operator==(const TItem& rhs) const {
  56. return Key == rhs.Key;
  57. }
  58. TKey Key;
  59. TValue Value;
  60. struct THash {
  61. size_t operator()(const TItem& item) const {
  62. return ::THash<TKey>()(item.Key);
  63. }
  64. size_t operator()(const TKey& key) const {
  65. return ::THash<TKey>()(key);
  66. }
  67. };
  68. struct TEqualTo {
  69. bool operator()(const TItem& lhs, const TItem& rhs) const {
  70. return lhs.Key == rhs.Key;
  71. }
  72. bool operator()(const TItem& lhs, const TKey& rhs) const {
  73. return lhs.Key == rhs;
  74. }
  75. bool operator()(const TKey& lhs, const TItem& rhs) const {
  76. return lhs == rhs.Key;
  77. }
  78. };
  79. };
  80. public:
  81. TItem* Insert(TItem* item) {
  82. List.PushBack(item);
  83. ++ItemsAmount;
  84. TotalSize += SizeProvider(item->Value);
  85. return RemoveIfOverflown();
  86. }
  87. TItem* RemoveIfOverflown() {
  88. TItem* deleted = nullptr;
  89. if (TotalSize > MaxSize && ItemsAmount > 1) {
  90. deleted = GetOldest();
  91. Erase(deleted);
  92. }
  93. return deleted;
  94. }
  95. TItem* GetOldest() {
  96. typename TListType::TIterator it = List.Begin();
  97. Y_ASSERT(it != List.End());
  98. return &*it;
  99. }
  100. void Erase(TItem* item) {
  101. item->Unlink();
  102. --ItemsAmount;
  103. TotalSize -= SizeProvider(item->Value);
  104. }
  105. void Promote(TItem* item) {
  106. item->Unlink();
  107. List.PushBack(item);
  108. }
  109. size_t GetSize() const {
  110. return ItemsAmount;
  111. }
  112. size_t GetTotalSize() const {
  113. return TotalSize;
  114. }
  115. size_t GetMaxSize() const {
  116. return MaxSize;
  117. }
  118. // It does not remove current items if newSize is less than TotalSize.
  119. // Caller should use RemoveIfOverflown to clean up list in this case
  120. void SetMaxSize(size_t newSize) {
  121. MaxSize = newSize;
  122. }
  123. private:
  124. typedef TIntrusiveList<TItem> TListType;
  125. TListType List;
  126. TSizeProvider SizeProvider;
  127. size_t ItemsAmount;
  128. size_t TotalSize;
  129. size_t MaxSize;
  130. };
  131. template <typename TKey, typename TValue, class TSizeProvider = TUniformSizeProvider<TValue>>
  132. class TLFUList {
  133. public:
  134. TLFUList(size_t maxSize, const TSizeProvider& sizeProvider = TSizeProvider())
  135. : List()
  136. , SizeProvider(sizeProvider)
  137. , ListSize(0)
  138. , MaxSize(maxSize)
  139. {
  140. }
  141. struct TItem: public TIntrusiveListItem<TItem> {
  142. typedef TIntrusiveListItem<TItem> TBase;
  143. explicit TItem(const TKey& key)
  144. : TBase()
  145. , Key(key)
  146. , Value()
  147. , Counter(0)
  148. {
  149. }
  150. explicit TItem(TKey&& key)
  151. : TBase()
  152. , Key(std::move(key))
  153. , Value()
  154. , Counter(0)
  155. {
  156. }
  157. template<typename TKeyRef, typename TValueRef>
  158. TItem(TKeyRef&& key, TValueRef&& value)
  159. : TBase()
  160. , Key(std::forward<TKeyRef>(key))
  161. , Value(std::forward<TValueRef>(value))
  162. , Counter(0)
  163. {
  164. }
  165. TItem(const TItem&) = default;
  166. TItem(TItem&&) = default;
  167. bool operator<(const TItem& rhs) const {
  168. return Key < rhs.Key;
  169. }
  170. bool operator==(const TItem& rhs) const {
  171. return Key == rhs.Key;
  172. }
  173. TKey Key;
  174. TValue Value;
  175. size_t Counter;
  176. struct THash {
  177. size_t operator()(const TItem& item) const {
  178. return ::THash<TKey>()(item.Key);
  179. }
  180. size_t operator()(const TKey& key) const {
  181. return ::THash<TKey>()(key);
  182. }
  183. };
  184. struct TEqualTo {
  185. bool operator()(const TItem& lhs, const TItem& rhs) const {
  186. return lhs.Key == rhs.Key;
  187. }
  188. bool operator()(const TItem& lhs, const TKey& rhs) const {
  189. return lhs.Key == rhs;
  190. }
  191. bool operator()(const TKey& lhs, const TItem& rhs) const {
  192. return lhs == rhs.Key;
  193. }
  194. };
  195. };
  196. public:
  197. TItem* Insert(TItem* item) {
  198. List.PushBack(item); // give a chance for promotion
  199. ListSize += SizeProvider(item->Value);
  200. return RemoveIfOverflown();
  201. }
  202. TItem* RemoveIfOverflown() {
  203. TItem* deleted = nullptr;
  204. if (ListSize > MaxSize) {
  205. deleted = GetLeastFrequentlyUsed();
  206. Erase(deleted);
  207. }
  208. return deleted;
  209. }
  210. TItem* GetLeastFrequentlyUsed() {
  211. typename TListType::TIterator it = List.Begin();
  212. Y_ASSERT(it != List.End());
  213. return &*it;
  214. }
  215. void Erase(TItem* item) {
  216. item->Unlink();
  217. ListSize -= SizeProvider(item->Value);
  218. }
  219. void Promote(TItem* item) {
  220. size_t counter = ++item->Counter;
  221. typename TListType::TIterator it = item;
  222. while (it != List.End() && counter >= it->Counter) {
  223. ++it;
  224. }
  225. item->LinkBefore(&*it);
  226. }
  227. size_t GetSize() const {
  228. return ListSize;
  229. }
  230. size_t GetMaxSize() const {
  231. return MaxSize;
  232. }
  233. // It does not remove current items if newSize is less than TotalSize.
  234. // Caller should use RemoveIfOverflown to clean up list in this case
  235. void SetMaxSize(size_t newSize) {
  236. MaxSize = newSize;
  237. }
  238. private:
  239. typedef TIntrusiveList<TItem> TListType;
  240. TListType List;
  241. TSizeProvider SizeProvider;
  242. size_t ListSize;
  243. size_t MaxSize;
  244. };
  245. // Least Weighted list
  246. // discards the least weighted items first
  247. // doesn't support promotion
  248. template <typename TKey, typename TValue, typename TWeight, typename TWeighter>
  249. class TLWList {
  250. public:
  251. TLWList(size_t maxSize)
  252. : Size(0)
  253. , MaxSize(maxSize)
  254. {
  255. }
  256. struct TItem {
  257. explicit TItem(const TKey& key)
  258. : Key(key)
  259. , Value()
  260. , Weight(TWeighter::Weight(Value))
  261. {
  262. }
  263. explicit TItem(TKey&& key)
  264. : Key(std::move(key))
  265. , Value()
  266. , Weight(TWeighter::Weight(Value))
  267. {
  268. }
  269. template<typename TKeyRef, typename TValueRef>
  270. TItem(TKeyRef&& key, TValueRef&& value)
  271. : Key(std::forward<TKeyRef>(key))
  272. , Value(std::forward<TValueRef>(value))
  273. , Weight(TWeighter::Weight(Value))
  274. {
  275. }
  276. TItem(const TItem&) = default;
  277. TItem(TItem&&) = default;
  278. bool operator<(const TItem& rhs) const {
  279. return Key < rhs.Key;
  280. }
  281. bool operator==(const TItem& rhs) const {
  282. return Key == rhs.Key;
  283. }
  284. TKey Key;
  285. TValue Value;
  286. TWeight Weight;
  287. struct THash {
  288. size_t operator()(const TItem& item) const {
  289. return ::THash<TKey>()(item.Key);
  290. }
  291. size_t operator()(const TKey& key) const {
  292. return ::THash<TKey>()(key);
  293. }
  294. };
  295. struct TEqualTo {
  296. bool operator()(const TItem& lhs, const TItem& rhs) const {
  297. return lhs.Key == rhs.Key;
  298. }
  299. bool operator()(const TItem& lhs, const TKey& rhs) const {
  300. return lhs.Key == rhs;
  301. }
  302. bool operator()(const TKey& lhs, const TItem& rhs) const {
  303. return lhs == rhs.Key;
  304. }
  305. };
  306. };
  307. struct THeapComparator {
  308. bool operator()(TItem* const item1, TItem* const item2) const {
  309. return item1->Weight > item2->Weight;
  310. }
  311. };
  312. public:
  313. TItem* Insert(TItem* item) {
  314. FixHeap();
  315. if (Size >= MaxSize && item->Weight < GetLightest()->Weight) {
  316. return item;
  317. }
  318. Heap.push_back(item);
  319. PushHeap(Heap.begin(), Heap.end(), THeapComparator());
  320. ++Size;
  321. return RemoveIfOverflown();
  322. }
  323. TItem* RemoveIfOverflown() {
  324. if (Size <= MaxSize) {
  325. return nullptr;
  326. }
  327. auto lightest = GetLightest();
  328. Erase(lightest);
  329. PopHeap(Heap.begin(), Heap.end(), THeapComparator());
  330. return lightest;
  331. }
  332. TItem* GetLightest() {
  333. FixHeap();
  334. Y_ASSERT(!Heap.empty());
  335. return Heap.front();
  336. }
  337. // This method doesn't remove items from the heap.
  338. // Erased items are stored in Removed set
  339. // and will be deleted on-access (using FixHeap method)
  340. void Erase(TItem* item) {
  341. Y_ASSERT(Size > 0);
  342. --Size;
  343. Removed.insert(item);
  344. }
  345. void Promote(TItem*) {
  346. // do nothing
  347. }
  348. [[nodiscard]] size_t GetSize() const {
  349. return Size;
  350. }
  351. size_t GetMaxSize() const {
  352. return MaxSize;
  353. }
  354. // It does not remove current items if newSize is less than TotalSize.
  355. // Caller should use RemoveIfOverflown to clean up list in this case
  356. void SetMaxSize(size_t newSize) {
  357. MaxSize = newSize;
  358. }
  359. void Clear() {
  360. Heap.clear();
  361. Removed.clear();
  362. Size = 0;
  363. }
  364. private:
  365. // Physically remove erased elements from the heap
  366. void FixHeap() {
  367. if (Removed.empty()) {
  368. return;
  369. }
  370. Heap.erase(std::remove_if(Heap.begin(), Heap.end(), [this](TItem* item) {
  371. return this->Removed.contains(item);
  372. }),
  373. Heap.end());
  374. MakeHeap(Heap.begin(), Heap.end(), THeapComparator());
  375. Removed.clear();
  376. Size = Heap.size();
  377. }
  378. private:
  379. TVector<TItem*> Heap;
  380. THashSet<TItem*> Removed;
  381. size_t Size;
  382. size_t MaxSize;
  383. };
  384. template <typename TKey, typename TValue, typename TListType, typename TDeleter, typename TAllocator = std::allocator<void>>
  385. class TCache {
  386. typedef typename TListType::TItem TItem;
  387. typedef typename TItem::THash THash;
  388. typedef THashMultiSet<TItem, THash, typename TItem::TEqualTo, TAllocator> TIndex;
  389. typedef typename TIndex::iterator TIndexIterator;
  390. typedef typename TIndex::const_iterator TIndexConstIterator;
  391. public:
  392. class TIterator {
  393. public:
  394. explicit TIterator(const TIndexConstIterator& iter)
  395. : Iter(iter)
  396. {
  397. }
  398. TValue& operator*() {
  399. return const_cast<TValue&>(Iter->Value);
  400. }
  401. TValue* operator->() {
  402. return const_cast<TValue*>(&Iter->Value);
  403. }
  404. bool operator==(const TIterator& rhs) const {
  405. return Iter == rhs.Iter;
  406. }
  407. bool operator!=(const TIterator& rhs) const {
  408. return Iter != rhs.Iter;
  409. }
  410. TIterator& operator++() {
  411. ++Iter;
  412. return *this;
  413. }
  414. const TKey& Key() const {
  415. return Iter->Key;
  416. }
  417. const TValue& Value() const {
  418. return Iter->Value;
  419. }
  420. friend class TCache<TKey, TValue, TListType, TDeleter, TAllocator>;
  421. private:
  422. TIndexConstIterator Iter;
  423. };
  424. TCache(TListType&& list, bool multiValue = false)
  425. : Index()
  426. , List(std::move(list))
  427. , MultiValue(multiValue)
  428. {
  429. }
  430. ~TCache() {
  431. Clear();
  432. }
  433. size_t Size() const {
  434. return Index.size();
  435. }
  436. TIterator Begin() const {
  437. return TIterator(Index.begin());
  438. }
  439. TIterator End() const {
  440. return TIterator(Index.end());
  441. }
  442. TIterator Find(const TKey& key) {
  443. TIndexIterator it = Index.find(key);
  444. if (it != Index.end())
  445. List.Promote(const_cast<TItem*>(&*it));
  446. return TIterator(it);
  447. }
  448. TIterator FindWithoutPromote(const TKey& key) const {
  449. return TIterator(Index.find(key));
  450. }
  451. // note: it shouldn't touch 'value' if it returns false.
  452. bool PickOut(const TKey& key, TValue* value) {
  453. Y_ASSERT(value);
  454. TIndexIterator it = Index.find(key);
  455. if (it == Index.end())
  456. return false;
  457. *value = std::move(it->Value);
  458. List.Erase(const_cast<TItem*>(&*it));
  459. Index.erase(it);
  460. Y_ASSERT(Index.size() == List.GetSize());
  461. return true;
  462. }
  463. bool Insert(const std::pair<TKey, TValue>& p) {
  464. return Insert(p.first, p.second);
  465. }
  466. template<typename TKeyRef, typename TValueRef>
  467. bool InsertImpl(TKeyRef&& key, TValueRef&& value) {
  468. if (!MultiValue && Index.find(key) != Index.end())
  469. return false;
  470. TIndexIterator it = Index.emplace(std::forward<TKeyRef>(key), std::forward<TValueRef>(value));
  471. TItem* insertedItem = const_cast<TItem*>(&*it);
  472. auto removedItem = List.Insert(insertedItem);
  473. auto insertedWasRemoved = removedItem == insertedItem;
  474. if (removedItem) {
  475. EraseFromIndex(removedItem);
  476. while ((removedItem = List.RemoveIfOverflown())) {
  477. insertedWasRemoved = insertedWasRemoved || insertedItem == removedItem;
  478. EraseFromIndex(removedItem);
  479. }
  480. }
  481. Y_ASSERT(Index.size() == List.GetSize());
  482. return !insertedWasRemoved;
  483. }
  484. // a lot of code calls Insert(key, {arguments for TValue constructor})
  485. // template version InsertImpl can not process this
  486. bool Insert(const TKey& key, const TValue& value) {
  487. return InsertImpl(key, value);
  488. }
  489. bool Insert(const TKey& key, TValue&& value) {
  490. return InsertImpl(key, std::move(value));
  491. }
  492. bool Insert(TKey&& key, const TValue& value) {
  493. return InsertImpl(std::move(key), value);
  494. }
  495. bool Insert(TKey&& key, TValue&& value) {
  496. return InsertImpl(std::move(key), std::move(value));
  497. }
  498. template<typename TKeyRef, typename TValueRef>
  499. void UpdateImpl(TKeyRef&& key, TValueRef&& value) {
  500. if (MultiValue)
  501. ythrow yexception() << "TCache: can't \"Update\" in multicache";
  502. TIterator it = Find(key);
  503. if (it != End()) {
  504. Erase(it);
  505. }
  506. InsertImpl(std::forward<TKeyRef>(key), std::forward<TValueRef>(value));
  507. Y_ASSERT(Index.size() == List.GetSize());
  508. }
  509. void Update(const TKey& key, const TValue& value) {
  510. UpdateImpl(key, value);
  511. }
  512. void Update(const TKey& key, TValue&& value) {
  513. UpdateImpl(key, std::move(value));
  514. }
  515. void Update(TKey&& key, const TValue& value) {
  516. UpdateImpl(std::move(key), value);
  517. }
  518. void Update(TKey&& key, TValue&& value) {
  519. UpdateImpl(std::move(key), std::move(value));
  520. }
  521. void Erase(TIterator it) {
  522. TItem* item = const_cast<TItem*>(&*it.Iter);
  523. List.Erase(item);
  524. TDeleter::Destroy(item->Value);
  525. Index.erase(it.Iter);
  526. Y_ASSERT(Index.size() == List.GetSize());
  527. }
  528. bool Empty() const {
  529. return Index.empty();
  530. }
  531. void Clear() {
  532. for (TIndexIterator it = Index.begin(); it != Index.end(); ++it) {
  533. TItem* item = const_cast<TItem*>(&*it);
  534. List.Erase(item);
  535. TDeleter::Destroy(item->Value);
  536. }
  537. Y_ASSERT(List.GetSize() == 0);
  538. Index.clear();
  539. }
  540. void SetMaxSize(size_t newSize) {
  541. List.SetMaxSize(newSize);
  542. TItem* removedItem = nullptr;
  543. while ((removedItem = List.RemoveIfOverflown())) {
  544. EraseFromIndex(removedItem);
  545. }
  546. Y_ASSERT(Index.size() == List.GetSize());
  547. }
  548. size_t GetMaxSize() const {
  549. return List.GetMaxSize();
  550. }
  551. void Reserve(size_t hint) {
  552. Index.reserve(hint);
  553. }
  554. typedef typename TIndex::node_allocator_type TNodeAllocatorType;
  555. TNodeAllocatorType& GetNodeAllocator() {
  556. return Index.GetNodeAllocator();
  557. }
  558. protected:
  559. TIndex Index;
  560. TListType List;
  561. bool MultiValue;
  562. TIterator FindByItem(TItem* item) {
  563. std::pair<TIndexIterator, TIndexIterator> p = Index.equal_range(*item);
  564. // we have to delete the exact unlinked item (there may be multiple items for one key)
  565. TIndexIterator it;
  566. for (it = p.first; it != p.second; ++it)
  567. if (&*it == item)
  568. break;
  569. return (it == p.second ? End() : TIterator(it));
  570. }
  571. void EraseFromIndex(TItem* item) {
  572. TDeleter::Destroy(item->Value);
  573. TIterator it = FindByItem(item);
  574. Y_ASSERT(it != End());
  575. Index.erase(it.Iter);
  576. }
  577. };
  578. struct TNoopDelete {
  579. template <class T>
  580. static inline void Destroy(const T&) noexcept {
  581. }
  582. };
  583. template <typename TKey, typename TValue, typename TDeleter = TNoopDelete, class TSizeProvider = TUniformSizeProvider<TValue>, typename TAllocator = std::allocator<void>>
  584. class TLRUCache: public TCache<TKey, TValue, TLRUList<TKey, TValue, TSizeProvider>, TDeleter, TAllocator> {
  585. using TListType = TLRUList<TKey, TValue, TSizeProvider>;
  586. typedef TCache<TKey, TValue, TListType, TDeleter, TAllocator> TBase;
  587. public:
  588. TLRUCache(size_t maxSize, bool multiValue = false, const TSizeProvider& sizeProvider = TSizeProvider())
  589. : TBase(TListType(maxSize, sizeProvider), multiValue)
  590. {
  591. }
  592. public:
  593. typedef typename TBase::TIterator TIterator;
  594. TValue& GetOldest() {
  595. return TBase::List.GetOldest()->Value;
  596. }
  597. TIterator FindOldest() {
  598. return TBase::Empty() ? TBase::End() : this->FindByItem(TBase::List.GetOldest());
  599. }
  600. size_t TotalSize() const {
  601. return TBase::List.GetTotalSize();
  602. }
  603. };
  604. template <typename TKey, typename TValue, typename TDeleter = TNoopDelete, typename TAllocator = std::allocator<void>, class TSizeProvider = TUniformSizeProvider<TValue>>
  605. class TLFUCache: public TCache<TKey, TValue, TLFUList<TKey, TValue, TSizeProvider>, TDeleter, TAllocator> {
  606. typedef TCache<TKey, TValue, TLFUList<TKey, TValue, TSizeProvider>, TDeleter, TAllocator> TBase;
  607. using TListType = TLFUList<TKey, TValue, TSizeProvider>;
  608. public:
  609. typedef typename TBase::TIterator TIterator;
  610. TLFUCache(size_t maxSize, bool multiValue = false, const TSizeProvider& sizeProvider = TSizeProvider())
  611. : TBase(TListType(maxSize, sizeProvider), multiValue)
  612. {
  613. }
  614. TValue& GetLeastFrequentlyUsed() {
  615. return TBase::List.GetLeastFrequentlyUsed()->Value;
  616. }
  617. TIterator FindLeastFrequentlyUsed() {
  618. return TBase::Empty() ? TBase::End() : this->FindByItem(TBase::List.GetLeastFrequentlyUsed());
  619. }
  620. };
  621. // Least Weighted cache
  622. // discards the least weighted items first
  623. // doesn't support promotion
  624. template <typename TKey, typename TValue, typename TWeight, typename TWeighter, typename TDeleter = TNoopDelete, typename TAllocator = std::allocator<void>>
  625. class TLWCache: public TCache<TKey, TValue, TLWList<TKey, TValue, TWeight, TWeighter>, TDeleter, TAllocator> {
  626. typedef TCache<TKey, TValue, TLWList<TKey, TValue, TWeight, TWeighter>, TDeleter, TAllocator> TBase;
  627. using TListType = TLWList<TKey, TValue, TWeight, TWeighter>;
  628. public:
  629. typedef typename TBase::TIterator TIterator;
  630. TLWCache(size_t maxSize, bool multiValue = false)
  631. : TBase(TListType(maxSize), multiValue)
  632. {
  633. }
  634. TValue& GetLightest() {
  635. return TBase::List.GetLightest()->Value;
  636. }
  637. TIterator FindLightest() {
  638. return TBase::Empty() ? TBase::End() : this->FindByItem(TBase::List.GetLightest());
  639. }
  640. };