![ContractedBlock.gif](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![ExpandedBlockStart.gif](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
public
class
LRUCache
<
TKey, TValue
>
:
where
TValue :
class
{
private Func < TValue, TKey > getKey;
private int maxCapacity;
private Dictionary < TKey, LinkedListNode < TValue >> buffer;
private LinkedList < TValue > list;
private ReaderWriterLockSlim locker;
public Func < TValue, TKey > GetKey
{
get { return getKey; }
}
public int Capacity
{
set { Interlocked.Exchange( ref maxCapacity, value); }
get { return maxCapacity; }
}
public int Count
{
get
{
locker.EnterReadLock();
try
{
return buffer.Count;
}
finally
{
locker.ExitReadLock();
}
}
}
public TValue LastItem
{
get
{
locker.EnterReadLock();
try
{
return list.Last.Value;
}
finally
{
locker.ExitReadLock();
}
}
}
internal ReaderWriterLockSlim Locker
{
get { return locker; }
}
public TValue this [TKey key]
{
set
{
if (value == null )
{
locker.EnterUpgradeableReadLock();
try
{
LinkedListNode < TValue > node;
if (buffer.TryGetValue(key, out node))
{
locker.EnterWriteLock();
try
{
buffer.Remove(key);
list.Remove(node);
}
finally
{
locker.ExitWriteLock();
}
}
}
finally
{
locker.ExitUpgradeableReadLock();
}
}
else
{
AddFirst(key, value);
}
}
get
{
locker.EnterReadLock();
try
{
LinkedListNode < TValue > node;
if (buffer.TryGetValue(key, out node))
{
locker.EnterWriteLock();
try
{
list.Remove(node);
list.AddFirst(node);
}
finally
{
locker.ExitWriteLock();
}
}
return node.Value;
}
finally
{
locker.ExitReadLock();
}
}
}
public LRUCache(Func < TValue, TKey > func)
: this (func, 500 )
{
}
public LRUCache(Func < TValue, TKey > func, int capacity)
{
this .getKey = func;
this .maxCapacity = capacity * 10 ;
buffer = new Dictionary < TKey, LinkedListNode < TValue >> (capacity);
list = new LinkedList < TValue > ();
locker = new ReaderWriterLockSlim();
}
public bool Contains(TKey key)
{
locker.EnterReadLock();
try
{
return buffer.ContainsKey(key);
}
finally
{
locker.ExitReadLock();
}
}
public void AddFirst(TKey key, TValue value)
{
AddFirst(key, value, Timeout.Infinite);
}
public void AddFirst(TKey key, TValue value, int timeout)
{
locker.EnterUpgradeableReadLock();
int count = buffer.Count;
if (count >= maxCapacity)
{
int needRemoveCount = count / 10 ;
locker.EnterWriteLock();
try
{
for ( int i = 0 ; i < needRemoveCount; i ++ )
{
buffer.Remove(getKey(list.Last.Value));
list.RemoveLast();
}
}
finally
{
locker.ExitWriteLock();
}
}
try
{
LinkedListNode < TValue > node;
if ( ! buffer.TryGetValue(key, out node))
{
node = new LinkedListNode < TValue > (value);
if (locker.TryEnterWriteLock(timeout))
{
buffer.Add(key, node);
list.AddFirst(node);
locker.ExitWriteLock();
}
}
}
finally
{
locker.ExitUpgradeableReadLock();
}
}
public void RemoveLast()
{
locker.EnterUpgradeableReadLock();
try
{
if (list.Last != null )
{
TKey key = getKey(list.Last.Value);
locker.EnterWriteLock();
try
{
buffer.Remove(key);
list.RemoveLast();
}
finally
{
locker.ExitWriteLock();
}
}
}
finally
{
locker.ExitUpgradeableReadLock();
}
}
public void Clear()
{
locker.EnterWriteLock();
try
{
buffer.Clear();
list.Clear();
}
finally
{
locker.ExitWriteLock();
}
}
}
{
private Func < TValue, TKey > getKey;
private int maxCapacity;
private Dictionary < TKey, LinkedListNode < TValue >> buffer;
private LinkedList < TValue > list;
private ReaderWriterLockSlim locker;
public Func < TValue, TKey > GetKey
{
get { return getKey; }
}
public int Capacity
{
set { Interlocked.Exchange( ref maxCapacity, value); }
get { return maxCapacity; }
}
public int Count
{
get
{
locker.EnterReadLock();
try
{
return buffer.Count;
}
finally
{
locker.ExitReadLock();
}
}
}
public TValue LastItem
{
get
{
locker.EnterReadLock();
try
{
return list.Last.Value;
}
finally
{
locker.ExitReadLock();
}
}
}
internal ReaderWriterLockSlim Locker
{
get { return locker; }
}
public TValue this [TKey key]
{
set
{
if (value == null )
{
locker.EnterUpgradeableReadLock();
try
{
LinkedListNode < TValue > node;
if (buffer.TryGetValue(key, out node))
{
locker.EnterWriteLock();
try
{
buffer.Remove(key);
list.Remove(node);
}
finally
{
locker.ExitWriteLock();
}
}
}
finally
{
locker.ExitUpgradeableReadLock();
}
}
else
{
AddFirst(key, value);
}
}
get
{
locker.EnterReadLock();
try
{
LinkedListNode < TValue > node;
if (buffer.TryGetValue(key, out node))
{
locker.EnterWriteLock();
try
{
list.Remove(node);
list.AddFirst(node);
}
finally
{
locker.ExitWriteLock();
}
}
return node.Value;
}
finally
{
locker.ExitReadLock();
}
}
}
public LRUCache(Func < TValue, TKey > func)
: this (func, 500 )
{
}
public LRUCache(Func < TValue, TKey > func, int capacity)
{
this .getKey = func;
this .maxCapacity = capacity * 10 ;
buffer = new Dictionary < TKey, LinkedListNode < TValue >> (capacity);
list = new LinkedList < TValue > ();
locker = new ReaderWriterLockSlim();
}
public bool Contains(TKey key)
{
locker.EnterReadLock();
try
{
return buffer.ContainsKey(key);
}
finally
{
locker.ExitReadLock();
}
}
public void AddFirst(TKey key, TValue value)
{
AddFirst(key, value, Timeout.Infinite);
}
public void AddFirst(TKey key, TValue value, int timeout)
{
locker.EnterUpgradeableReadLock();
int count = buffer.Count;
if (count >= maxCapacity)
{
int needRemoveCount = count / 10 ;
locker.EnterWriteLock();
try
{
for ( int i = 0 ; i < needRemoveCount; i ++ )
{
buffer.Remove(getKey(list.Last.Value));
list.RemoveLast();
}
}
finally
{
locker.ExitWriteLock();
}
}
try
{
LinkedListNode < TValue > node;
if ( ! buffer.TryGetValue(key, out node))
{
node = new LinkedListNode < TValue > (value);
if (locker.TryEnterWriteLock(timeout))
{
buffer.Add(key, node);
list.AddFirst(node);
locker.ExitWriteLock();
}
}
}
finally
{
locker.ExitUpgradeableReadLock();
}
}
public void RemoveLast()
{
locker.EnterUpgradeableReadLock();
try
{
if (list.Last != null )
{
TKey key = getKey(list.Last.Value);
locker.EnterWriteLock();
try
{
buffer.Remove(key);
list.RemoveLast();
}
finally
{
locker.ExitWriteLock();
}
}
}
finally
{
locker.ExitUpgradeableReadLock();
}
}
public void Clear()
{
locker.EnterWriteLock();
try
{
buffer.Clear();
list.Clear();
}
finally
{
locker.ExitWriteLock();
}
}
}