@@ -214,6 +214,50 @@ class MM2Q {
214214 size_t hotPercent,
215215 size_t coldPercent,
216216 uint32_t mmReconfigureInterval)
217+ : Config(time,
218+ ratio,
219+ updateOnW,
220+ updateOnR,
221+ tryLockU,
222+ rebalanceOnRecordAccs,
223+ hotPercent,
224+ coldPercent,
225+ mmReconfigureInterval,
226+ false ) {}
227+
228+ // @param time the LRU refresh time.
229+ // An item will be promoted only once in each
230+ // lru refresh time depite the
231+ // number of accesses it gets.
232+ // @param ratio the LRU refresh ratio. The ratio times the
233+ // oldest element's lifetime in warm queue
234+ // would be the minimum value of LRU refresh
235+ // time.
236+ // @param udpateOnW whether to promote the item on write
237+ // @param updateOnR whether to promote the item on read
238+ // @param tryLockU whether to use a try lock when doing
239+ // update.
240+ // @param rebalanceOnRecordAccs whether to do rebalance on access. If set
241+ // to false, rebalance only happens when
242+ // items are added or removed to the queue.
243+ // @param hotPercent percentage number for the size of the hot
244+ // queue in the overall size.
245+ // @param coldPercent percentage number for the size of the cold
246+ // queue in the overall size.
247+ // @param mmReconfigureInterval Time interval for recalculating lru
248+ // refresh time according to the ratio.
249+ // useCombinedLockForIterators Whether to use combined locking for
250+ // withEvictionIterator
251+ Config (uint32_t time,
252+ double ratio,
253+ bool updateOnW,
254+ bool updateOnR,
255+ bool tryLockU,
256+ bool rebalanceOnRecordAccs,
257+ size_t hotPercent,
258+ size_t coldPercent,
259+ uint32_t mmReconfigureInterval,
260+ bool useCombinedLockForIterators)
217261 : defaultLruRefreshTime(time),
218262 lruRefreshRatio (ratio),
219263 updateOnWrite(updateOnW),
@@ -223,7 +267,8 @@ class MM2Q {
223267 hotSizePercent(hotPercent),
224268 coldSizePercent(coldPercent),
225269 mmReconfigureIntervalSecs(
226- std::chrono::seconds (mmReconfigureInterval)) {
270+ std::chrono::seconds (mmReconfigureInterval)),
271+ useCombinedLockForIterators(useCombinedLockForIterators) {
227272 checkLruSizes ();
228273 }
229274
@@ -306,6 +351,9 @@ class MM2Q {
306351 // Minimum interval between reconfigurations. If 0, reconfigure is never
307352 // called.
308353 std::chrono::seconds mmReconfigureIntervalSecs{};
354+
355+ // Whether to use combined locking for withEvictionIterator.
356+ bool useCombinedLockForIterators{false };
309357 };
310358
311359 // The container object which can be used to keep track of objects of type
@@ -347,22 +395,24 @@ class MM2Q {
347395 Container (const Container&) = delete;
348396 Container& operator =(const Container&) = delete ;
349397
398+ using Iterator = typename LruList::Iterator;
399+
350400 // context for iterating the MM container. At any given point of time,
351401 // there can be only one iterator active since we need to lock the LRU for
352402 // iteration. we can support multiple iterators at same time, by using a
353403 // shared ptr in the context for the lock holder in the future.
354- class Iterator : public LruList :: Iterator {
404+ class LockedIterator : public Iterator {
355405 public:
356406 // noncopyable but movable.
357- Iterator (const Iterator &) = delete ;
358- Iterator & operator =(const Iterator &) = delete ;
407+ LockedIterator (const LockedIterator &) = delete ;
408+ LockedIterator & operator =(const LockedIterator &) = delete ;
359409
360- Iterator (Iterator &&) noexcept = default ;
410+ LockedIterator (LockedIterator &&) noexcept = default ;
361411
362412 // 1. Invalidate this iterator
363413 // 2. Unlock
364414 void destroy () {
365- LruList:: Iterator::reset ();
415+ Iterator::reset ();
366416 if (l_.owns_lock ()) {
367417 l_.unlock ();
368418 }
@@ -373,15 +423,15 @@ class MM2Q {
373423 if (!l_.owns_lock ()) {
374424 l_.lock ();
375425 }
376- LruList:: Iterator::resetToBegin ();
426+ Iterator::resetToBegin ();
377427 }
378428
379429 private:
380430 // private because it's easy to misuse and cause deadlock for MM2Q
381- Iterator & operator =(Iterator &&) noexcept = default ;
431+ LockedIterator & operator =(LockedIterator &&) noexcept = default ;
382432
383433 // create an lru iterator with the lock being held.
384- Iterator (LockHolder l, const typename LruList:: Iterator& iter) noexcept ;
434+ LockedIterator (LockHolder l, const Iterator& iter) noexcept ;
385435
386436 // only the container can create iterators
387437 friend Container<T, HookPtr>;
@@ -422,7 +472,7 @@ class MM2Q {
422472
423473 // same as the above but uses an iterator context. The iterator is updated
424474 // on removal of the corresponding node to point to the next node. The
425- // iterator context holds the lock on the lru .
475+ // iterator context is responsible for locking .
426476 //
427477 // iterator will be advanced to the next node after removing the node
428478 //
@@ -445,7 +495,12 @@ class MM2Q {
445495 // Obtain an iterator that start from the tail and can be used
446496 // to search for evictions. This iterator holds a lock to this
447497 // container and only one such iterator can exist at a time
448- Iterator getEvictionIterator () const noexcept ;
498+ LockedIterator getEvictionIterator () const noexcept ;
499+
500+ // Execute provided function under container lock. Function gets
501+ // Iterator passed as parameter.
502+ template <typename F>
503+ void withEvictionIterator (F&& f);
449504
450505 // get the current config as a copy
451506 Config getConfig () const ;
0 commit comments