1 namespace System.Web.Mvc {
3 using System.Collections.Generic;
4 using System.Diagnostics.CodeAnalysis;
5 using System.Threading;
7 [SuppressMessage("Microsoft.Design", "CA1001:TypesThatOwnDisposableFieldsShouldBeDisposable", Justification = "Instances of this type are meant to be singletons.")]
8 internal abstract class ReaderWriterCache<TKey, TValue> {
10 private readonly Dictionary<TKey, TValue> _cache;
11 private readonly ReaderWriterLockSlim _rwLock = new ReaderWriterLockSlim();
13 protected ReaderWriterCache()
17 protected ReaderWriterCache(IEqualityComparer<TKey> comparer) {
18 _cache = new Dictionary<TKey, TValue>(comparer);
21 protected Dictionary<TKey, TValue> Cache {
27 protected TValue FetchOrCreateItem(TKey key, Func<TValue> creator) {
28 // first, see if the item already exists in the cache
29 _rwLock.EnterReadLock();
32 if (_cache.TryGetValue(key, out existingEntry)) {
37 _rwLock.ExitReadLock();
40 // insert the new item into the cache
41 TValue newEntry = creator();
42 _rwLock.EnterWriteLock();
45 if (_cache.TryGetValue(key, out existingEntry)) {
46 // another thread already inserted an item, so use that one
50 _cache[key] = newEntry;
54 _rwLock.ExitWriteLock();