Merge pull request #249 from pcc/xgetinputfocus
[mono.git] / mcs / class / System.Web.Mvc3 / Mvc / ReaderWriterCache`2.cs
1 namespace System.Web.Mvc {
2     using System;
3     using System.Collections.Generic;
4     using System.Diagnostics.CodeAnalysis;
5     using System.Threading;
6
7     [SuppressMessage("Microsoft.Design", "CA1001:TypesThatOwnDisposableFieldsShouldBeDisposable", Justification = "Instances of this type are meant to be singletons.")]
8     internal abstract class ReaderWriterCache<TKey, TValue> {
9
10         private readonly Dictionary<TKey, TValue> _cache;
11         private readonly ReaderWriterLockSlim _rwLock = new ReaderWriterLockSlim();
12
13         protected ReaderWriterCache()
14             : this(null) {
15         }
16
17         protected ReaderWriterCache(IEqualityComparer<TKey> comparer) {
18             _cache = new Dictionary<TKey, TValue>(comparer);
19         }
20
21         protected Dictionary<TKey, TValue> Cache {
22             get {
23                 return _cache;
24             }
25         }
26
27         protected TValue FetchOrCreateItem(TKey key, Func<TValue> creator) {
28             // first, see if the item already exists in the cache
29             _rwLock.EnterReadLock();
30             try {
31                 TValue existingEntry;
32                 if (_cache.TryGetValue(key, out existingEntry)) {
33                     return existingEntry;
34                 }
35             }
36             finally {
37                 _rwLock.ExitReadLock();
38             }
39
40             // insert the new item into the cache
41             TValue newEntry = creator();
42             _rwLock.EnterWriteLock();
43             try {
44                 TValue existingEntry;
45                 if (_cache.TryGetValue(key, out existingEntry)) {
46                     // another thread already inserted an item, so use that one
47                     return existingEntry;
48                 }
49
50                 _cache[key] = newEntry;
51                 return newEntry;
52             }
53             finally {
54                 _rwLock.ExitWriteLock();
55             }
56         }
57
58     }
59 }