@@ -214,6 +214,50 @@ class MM2Q {
214
214
size_t hotPercent,
215
215
size_t coldPercent,
216
216
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)
217
261
: defaultLruRefreshTime(time),
218
262
lruRefreshRatio (ratio),
219
263
updateOnWrite(updateOnW),
@@ -223,7 +267,8 @@ class MM2Q {
223
267
hotSizePercent(hotPercent),
224
268
coldSizePercent(coldPercent),
225
269
mmReconfigureIntervalSecs(
226
- std::chrono::seconds (mmReconfigureInterval)) {
270
+ std::chrono::seconds (mmReconfigureInterval)),
271
+ useCombinedLockForIterators(useCombinedLockForIterators) {
227
272
checkLruSizes ();
228
273
}
229
274
@@ -306,6 +351,9 @@ class MM2Q {
306
351
// Minimum interval between reconfigurations. If 0, reconfigure is never
307
352
// called.
308
353
std::chrono::seconds mmReconfigureIntervalSecs{};
354
+
355
+ // Whether to use combined locking for withEvictionIterator.
356
+ bool useCombinedLockForIterators{false };
309
357
};
310
358
311
359
// The container object which can be used to keep track of objects of type
@@ -347,22 +395,24 @@ class MM2Q {
347
395
Container (const Container&) = delete;
348
396
Container& operator =(const Container&) = delete ;
349
397
398
+ using Iterator = typename LruList::Iterator;
399
+
350
400
// context for iterating the MM container. At any given point of time,
351
401
// there can be only one iterator active since we need to lock the LRU for
352
402
// iteration. we can support multiple iterators at same time, by using a
353
403
// shared ptr in the context for the lock holder in the future.
354
- class Iterator : public LruList :: Iterator {
404
+ class LockedIterator : public Iterator {
355
405
public:
356
406
// 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 ;
359
409
360
- Iterator (Iterator &&) noexcept = default ;
410
+ LockedIterator (LockedIterator &&) noexcept = default ;
361
411
362
412
// 1. Invalidate this iterator
363
413
// 2. Unlock
364
414
void destroy () {
365
- LruList:: Iterator::reset ();
415
+ Iterator::reset ();
366
416
if (l_.owns_lock ()) {
367
417
l_.unlock ();
368
418
}
@@ -373,15 +423,15 @@ class MM2Q {
373
423
if (!l_.owns_lock ()) {
374
424
l_.lock ();
375
425
}
376
- LruList:: Iterator::resetToBegin ();
426
+ Iterator::resetToBegin ();
377
427
}
378
428
379
429
private:
380
430
// private because it's easy to misuse and cause deadlock for MM2Q
381
- Iterator & operator =(Iterator &&) noexcept = default ;
431
+ LockedIterator & operator =(LockedIterator &&) noexcept = default ;
382
432
383
433
// 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 ;
385
435
386
436
// only the container can create iterators
387
437
friend Container<T, HookPtr>;
@@ -422,7 +472,7 @@ class MM2Q {
422
472
423
473
// same as the above but uses an iterator context. The iterator is updated
424
474
// 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 .
426
476
//
427
477
// iterator will be advanced to the next node after removing the node
428
478
//
@@ -445,7 +495,12 @@ class MM2Q {
445
495
// Obtain an iterator that start from the tail and can be used
446
496
// to search for evictions. This iterator holds a lock to this
447
497
// 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);
449
504
450
505
// get the current config as a copy
451
506
Config getConfig () const ;
0 commit comments