@@ -144,15 +144,17 @@ class MMLru {
144144 bool updateOnR,
145145 bool tryLockU,
146146 uint8_t ipSpec,
147- uint32_t mmReconfigureInterval)
147+ uint32_t mmReconfigureInterval,
148+ bool useCombinedLockForIterators = false )
148149 : defaultLruRefreshTime(time),
149150 lruRefreshRatio (ratio),
150151 updateOnWrite(updateOnW),
151152 updateOnRead(updateOnR),
152153 tryLockUpdate(tryLockU),
153154 lruInsertionPointSpec(ipSpec),
154155 mmReconfigureIntervalSecs(
155- std::chrono::seconds (mmReconfigureInterval)) {}
156+ std::chrono::seconds (mmReconfigureInterval)),
157+ useCombinedLockForIterators(useCombinedLockForIterators) {}
156158
157159 Config () = default;
158160 Config (const Config& rhs) = default;
@@ -195,6 +197,9 @@ class MMLru {
195197 // lruInsertionPointSpec = 2, we insert at a point 1/4th from tail
196198 uint8_t lruInsertionPointSpec{0 };
197199
200+ // Whether to use combined locking for withEvictionIterator.
201+ bool useCombinedLockForIterators{false };
202+
198203 // Minimum interval between reconfigurations. If 0, reconfigure is never
199204 // called.
200205 std::chrono::seconds mmReconfigureIntervalSecs{};
@@ -234,22 +239,24 @@ class MMLru {
234239 Container (const Container&) = delete;
235240 Container& operator =(const Container&) = delete ;
236241
242+ using Iterator = typename LruList::Iterator;
243+
237244 // context for iterating the MM container. At any given point of time,
238245 // there can be only one iterator active since we need to lock the LRU for
239246 // iteration. we can support multiple iterators at same time, by using a
240247 // shared ptr in the context for the lock holder in the future.
241- class Iterator : public LruList :: Iterator {
248+ class LockedIterator : public Iterator {
242249 public:
243250 // noncopyable but movable.
244- Iterator (const Iterator &) = delete ;
245- Iterator & operator =(const Iterator &) = delete ;
251+ LockedIterator (const LockedIterator &) = delete ;
252+ LockedIterator & operator =(const LockedIterator &) = delete ;
246253
247- Iterator (Iterator &&) noexcept = default ;
254+ LockedIterator (LockedIterator &&) noexcept = default ;
248255
249256 // 1. Invalidate this iterator
250257 // 2. Unlock
251258 void destroy () {
252- LruList:: Iterator::reset ();
259+ Iterator::reset ();
253260 if (l_.owns_lock ()) {
254261 l_.unlock ();
255262 }
@@ -260,15 +267,15 @@ class MMLru {
260267 if (!l_.owns_lock ()) {
261268 l_.lock ();
262269 }
263- LruList:: Iterator::resetToBegin ();
270+ Iterator::resetToBegin ();
264271 }
265272
266273 private:
267274 // private because it's easy to misuse and cause deadlock for MMLru
268- Iterator & operator =(Iterator &&) noexcept = default ;
275+ LockedIterator & operator =(LockedIterator &&) noexcept = default ;
269276
270277 // create an lru iterator with the lock being held.
271- Iterator (LockHolder l, const typename LruList:: Iterator& iter) noexcept ;
278+ LockedIterator (LockHolder l, const Iterator& iter) noexcept ;
272279
273280 // only the container can create iterators
274281 friend Container<T, HookPtr>;
@@ -307,10 +314,9 @@ class MMLru {
307314 // state of node is unchanged.
308315 bool remove (T& node) noexcept ;
309316
310- using Iterator = Iterator;
311317 // same as the above but uses an iterator context. The iterator is updated
312318 // on removal of the corresponding node to point to the next node. The
313- // iterator context holds the lock on the lru .
319+ // iterator context is responsible for locking .
314320 //
315321 // iterator will be advanced to the next node after removing the node
316322 //
@@ -330,7 +336,12 @@ class MMLru {
330336 // Obtain an iterator that start from the tail and can be used
331337 // to search for evictions. This iterator holds a lock to this
332338 // container and only one such iterator can exist at a time
333- Iterator getEvictionIterator () const noexcept ;
339+ LockedIterator getEvictionIterator () const noexcept ;
340+
341+ // Execute provided function under container lock. Function gets
342+ // iterator passed as parameter.
343+ template <typename F>
344+ void withEvictionIterator (F&& f);
334345
335346 // get copy of current config
336347 Config getConfig () const ;
0 commit comments