Fix bugs in sizing TableLayoutPanel (Xamarin bug 18638)
[mono.git] / mcs / class / System.Web.Mvc2 / System.Web.Mvc / ReaderWriterCache`2.cs
1 /* ****************************************************************************\r
2  *\r
3  * Copyright (c) Microsoft Corporation. All rights reserved.\r
4  *\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
8  *\r
9  * You must not remove this notice, or any other, from this software.\r
10  *\r
11  * ***************************************************************************/\r
12 \r
13 namespace System.Web.Mvc {\r
14     using System;\r
15     using System.Collections.Generic;\r
16     using System.Diagnostics.CodeAnalysis;\r
17     using System.Threading;\r
18 \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
22 \r
23         private readonly Dictionary<TKey, TValue> _cache;\r
24         private readonly ReaderWriterLockSlim _rwLock = new ReaderWriterLockSlim();\r
25 \r
26         protected ReaderWriterCache()\r
27             : this(null) {\r
28         }\r
29 \r
30         protected ReaderWriterCache(IEqualityComparer<TKey> comparer) {\r
31             _cache = new Dictionary<TKey, TValue>(comparer);\r
32         }\r
33 \r
34         protected Dictionary<TKey, TValue> Cache {\r
35             get {\r
36                 return _cache;\r
37             }\r
38         }\r
39 \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
43             try {\r
44                 TValue existingEntry;\r
45                 if (_cache.TryGetValue(key, out existingEntry)) {\r
46                     return existingEntry;\r
47                 }\r
48             }\r
49             finally {\r
50                 _rwLock.ExitReadLock();\r
51             }\r
52 \r
53             // insert the new item into the cache\r
54             TValue newEntry = creator();\r
55             _rwLock.EnterWriteLock();\r
56             try {\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
61                 }\r
62 \r
63                 _cache[key] = newEntry;\r
64                 return newEntry;\r
65             }\r
66             finally {\r
67                 _rwLock.ExitWriteLock();\r
68             }\r
69         }\r
70 \r
71     }\r
72 }\r