73 lines
2.4 KiB
C#
73 lines
2.4 KiB
C#
|
/* ****************************************************************************
|
|||
|
*
|
|||
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|||
|
*
|
|||
|
* This software is subject to the Microsoft Public License (Ms-PL).
|
|||
|
* A copy of the license can be found in the license.htm file included
|
|||
|
* in this distribution.
|
|||
|
*
|
|||
|
* You must not remove this notice, or any other, from this software.
|
|||
|
*
|
|||
|
* ***************************************************************************/
|
|||
|
|
|||
|
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();
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
}
|