-
Notifications
You must be signed in to change notification settings - Fork 34
/
Copy pathConstrainedCache.cs
65 lines (52 loc) · 2.33 KB
/
ConstrainedCache.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
// Copyright (c) Imazen LLC.
// No part of this project, including this file, may be copied, modified,
// propagated, or distributed except as permitted in COPYRIGHT.txt.
// Licensed under the GNU Affero General Public License, Version 3.0.
// Commercial licenses available at http://imageresizing.net/
using System;
using System.Collections.Generic;
namespace Imazen.DiskCache.SourceMemCache {
internal class ConstrainedCache<TK,TV> {
public delegate long SizeCalculationDelegate(TK key, TV value);
public ConstrainedCache(IEqualityComparer<TK> keyComparer, SizeCalculationDelegate calculator, long maxBytes, TimeSpan usageWindow, TimeSpan minCleanupInterval) {
EventCountingStrategy s = new EventCountingStrategy
{
MaxBytesUsed = maxBytes,
MinimumCleanupInterval = minCleanupInterval,
CounterGranularity = 16
};
usage = new EventCountingDictionary<TK>(keyComparer, usageWindow, s);
usage.CounterRemoved += usage_CounterRemoved;
data = new Dictionary<TK, TV>(keyComparer);
this.calculator = calculator;
}
private readonly SizeCalculationDelegate calculator;
private readonly EventCountingDictionary<TK> usage;
private readonly Dictionary<TK,TV> data;
/// <summary>
/// The estimated ram usage for the entire cache. Relies upon the accuracy of the calculator delegate
/// </summary>
public long ReportedBytesUsed => usage.ReportedBytesUsed;
private readonly object lockSync = new object();
public TV Get(TK key) {
lock (lockSync) {
bool found = data.TryGetValue(key, out var val);
if (found) usage.Increment(key, 0);
return found ? val : default;
}
}
public void Set(TK key, TV val) {
lock (lockSync) {
data[key] = val;
usage.Increment(key, calculator(key, val) + 32);
}
}
public void PingCleanup() { usage.PingCleanup(); }
void usage_CounterRemoved(EventCountingDictionary<TK> sender, TK key, int value) {
//May be expected inside usage.lockSync AND lockSync
lock (lockSync) {
data.Remove(key);
}
}
}
}