@@ -121,7 +121,8 @@ class MMLru {
121121 bool updateOnR,
122122 bool tryLockU,
123123 uint8_t ipSpec)
124- : Config(time, ratio, updateOnW, updateOnR, tryLockU, ipSpec, 0 ) {}
124+ : Config(
125+ time, ratio, updateOnW, updateOnR, tryLockU, ipSpec, 0 , false ) {}
125126
126127 // @param time the LRU refresh time in seconds.
127128 // An item will be promoted only once in each lru refresh
@@ -138,21 +139,25 @@ class MMLru {
138139 // value 2 means 1/4 from the end of LRU.
139140 // @param mmReconfigureInterval Time interval for recalculating lru
140141 // refresh time according to the ratio.
142+ // useCombinedLockForIterators Whether to use combined locking for
143+ // withEvictionIterator
141144 Config (uint32_t time,
142145 double ratio,
143146 bool updateOnW,
144147 bool updateOnR,
145148 bool tryLockU,
146149 uint8_t ipSpec,
147- uint32_t mmReconfigureInterval)
150+ uint32_t mmReconfigureInterval,
151+ bool useCombinedLockForIterators)
148152 : defaultLruRefreshTime(time),
149153 lruRefreshRatio (ratio),
150154 updateOnWrite(updateOnW),
151155 updateOnRead(updateOnR),
152156 tryLockUpdate(tryLockU),
153157 lruInsertionPointSpec(ipSpec),
154158 mmReconfigureIntervalSecs(
155- std::chrono::seconds (mmReconfigureInterval)) {}
159+ std::chrono::seconds (mmReconfigureInterval)),
160+ useCombinedLockForIterators(useCombinedLockForIterators) {}
156161
157162 Config () = default;
158163 Config (const Config& rhs) = default;
@@ -195,6 +200,9 @@ class MMLru {
195200 // lruInsertionPointSpec = 2, we insert at a point 1/4th from tail
196201 uint8_t lruInsertionPointSpec{0 };
197202
203+ // Whether to use combined locking for withEvictionIterator.
204+ bool useCombinedLockForIterators{false };
205+
198206 // Minimum interval between reconfigurations. If 0, reconfigure is never
199207 // called.
200208 std::chrono::seconds mmReconfigureIntervalSecs{};
@@ -234,22 +242,24 @@ class MMLru {
234242 Container (const Container&) = delete;
235243 Container& operator =(const Container&) = delete ;
236244
245+ using Iterator = typename LruList::Iterator;
246+
237247 // context for iterating the MM container. At any given point of time,
238248 // there can be only one iterator active since we need to lock the LRU for
239249 // iteration. we can support multiple iterators at same time, by using a
240250 // shared ptr in the context for the lock holder in the future.
241- class Iterator : public LruList :: Iterator {
251+ class LockedIterator : public Iterator {
242252 public:
243253 // noncopyable but movable.
244- Iterator (const Iterator &) = delete ;
245- Iterator & operator =(const Iterator &) = delete ;
254+ LockedIterator (const LockedIterator &) = delete ;
255+ LockedIterator & operator =(const LockedIterator &) = delete ;
246256
247- Iterator (Iterator &&) noexcept = default ;
257+ LockedIterator (LockedIterator &&) noexcept = default ;
248258
249259 // 1. Invalidate this iterator
250260 // 2. Unlock
251261 void destroy () {
252- LruList:: Iterator::reset ();
262+ Iterator::reset ();
253263 if (l_.owns_lock ()) {
254264 l_.unlock ();
255265 }
@@ -260,15 +270,15 @@ class MMLru {
260270 if (!l_.owns_lock ()) {
261271 l_.lock ();
262272 }
263- LruList:: Iterator::resetToBegin ();
273+ Iterator::resetToBegin ();
264274 }
265275
266276 private:
267277 // private because it's easy to misuse and cause deadlock for MMLru
268- Iterator & operator =(Iterator &&) noexcept = default ;
278+ LockedIterator & operator =(LockedIterator &&) noexcept = default ;
269279
270280 // create an lru iterator with the lock being held.
271- Iterator (LockHolder l, const typename LruList:: Iterator& iter) noexcept ;
281+ LockedIterator (LockHolder l, const Iterator& iter) noexcept ;
272282
273283 // only the container can create iterators
274284 friend Container<T, HookPtr>;
@@ -307,10 +317,9 @@ class MMLru {
307317 // state of node is unchanged.
308318 bool remove (T& node) noexcept ;
309319
310- using Iterator = Iterator;
311320 // same as the above but uses an iterator context. The iterator is updated
312321 // on removal of the corresponding node to point to the next node. The
313- // iterator context holds the lock on the lru .
322+ // iterator context is responsible for locking .
314323 //
315324 // iterator will be advanced to the next node after removing the node
316325 //
@@ -330,7 +339,12 @@ class MMLru {
330339 // Obtain an iterator that start from the tail and can be used
331340 // to search for evictions. This iterator holds a lock to this
332341 // container and only one such iterator can exist at a time
333- Iterator getEvictionIterator () const noexcept ;
342+ LockedIterator getEvictionIterator () const noexcept ;
343+
344+ // Execute provided function under container lock. Function gets
345+ // iterator passed as parameter.
346+ template <typename F>
347+ void withEvictionIterator (F&& f);
334348
335349 // get copy of current config
336350 Config getConfig () const ;
0 commit comments