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
|
namespace System.Web.Mvc {
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Threading;
[SuppressMessage("Microsoft.Design", "CA1001:TypesThatOwnDisposableFieldsShouldBeDisposable", Justification = "Instances of this type are meant to be singletons.")]
internal abstract class ReaderWriterCache<TKey, TValue> {
private readonly Dictionary<TKey, TValue> _cache;
private readonly ReaderWriterLockSlim _rwLock = new ReaderWriterLockSlim();
protected ReaderWriterCache()
: this(null) {
}
protected ReaderWriterCache(IEqualityComparer<TKey> comparer) {
_cache = new Dictionary<TKey, TValue>(comparer);
}
protected Dictionary<TKey, TValue> Cache {
get {
return _cache;
}
}
protected TValue FetchOrCreateItem(TKey key, Func<TValue> creator) {
// first, see if the item already exists in the cache
_rwLock.EnterReadLock();
try {
TValue existingEntry;
if (_cache.TryGetValue(key, out existingEntry)) {
return existingEntry;
}
}
finally {
_rwLock.ExitReadLock();
}
// insert the new item into the cache
TValue newEntry = creator();
_rwLock.EnterWriteLock();
try {
TValue existingEntry;
if (_cache.TryGetValue(key, out existingEntry)) {
// another thread already inserted an item, so use that one
return existingEntry;
}
_cache[key] = newEntry;
return newEntry;
}
finally {
_rwLock.ExitWriteLock();
}
}
}
}
|