1 /* ****************************************************************************
\r
3 * Copyright (c) Microsoft Corporation. All rights reserved.
\r
5 * This software is subject to the Microsoft Public License (Ms-PL).
\r
6 * A copy of the license can be found in the license.htm file included
\r
7 * in this distribution.
\r
9 * You must not remove this notice, or any other, from this software.
\r
11 * ***************************************************************************/
\r
13 namespace System.Web.Mvc {
\r
15 using System.Collections.Generic;
\r
16 using System.Diagnostics.CodeAnalysis;
\r
17 using System.Threading;
\r
19 [SuppressMessage("Microsoft.Design", "CA1001:TypesThatOwnDisposableFieldsShouldBeDisposable",
\r
20 Justification = "Instances of this type are meant to be singletons.")]
\r
21 internal abstract class ReaderWriterCache<TKey, TValue> {
\r
23 private readonly Dictionary<TKey, TValue> _cache;
\r
24 private readonly ReaderWriterLockSlim _rwLock = new ReaderWriterLockSlim();
\r
26 protected ReaderWriterCache()
\r
30 protected ReaderWriterCache(IEqualityComparer<TKey> comparer) {
\r
31 _cache = new Dictionary<TKey, TValue>(comparer);
\r
34 protected Dictionary<TKey, TValue> Cache {
\r
40 protected TValue FetchOrCreateItem(TKey key, Func<TValue> creator) {
\r
41 // first, see if the item already exists in the cache
\r
42 _rwLock.EnterReadLock();
\r
44 TValue existingEntry;
\r
45 if (_cache.TryGetValue(key, out existingEntry)) {
\r
46 return existingEntry;
\r
50 _rwLock.ExitReadLock();
\r
53 // insert the new item into the cache
\r
54 TValue newEntry = creator();
\r
55 _rwLock.EnterWriteLock();
\r
57 TValue existingEntry;
\r
58 if (_cache.TryGetValue(key, out existingEntry)) {
\r
59 // another thread already inserted an item, so use that one
\r
60 return existingEntry;
\r
63 _cache[key] = newEntry;
\r
67 _rwLock.ExitWriteLock();
\r