Jo Shields a575963da9 Imported Upstream version 3.6.0
Former-commit-id: da6be194a6b1221998fc28233f2503bd61dd9d14
2014-08-13 10:39:27 +01:00

60 lines
1.9 KiB
C#

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();
}
}
}
}