From 82cb85bba1c0ba0e2ac8343f9f6716a6afbf9f82 Mon Sep 17 00:00:00 2001 From: Renaud Paquay Date: Wed, 28 Jul 2010 13:06:11 -0700 Subject: [PATCH] Fix concurrency issue accessing Dictionary instance --HG-- branch : dev --- src/Orchard/Caching/Cache.cs | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/src/Orchard/Caching/Cache.cs b/src/Orchard/Caching/Cache.cs index 4f0bb402a..20e43cf1e 100644 --- a/src/Orchard/Caching/Cache.cs +++ b/src/Orchard/Caching/Cache.cs @@ -1,31 +1,35 @@ using System; +using System.Collections.Concurrent; using System.Collections.Generic; using System.Linq; namespace Orchard.Caching { public class Cache : ICache { - private readonly Dictionary _entries; + private readonly ConcurrentDictionary _entries; public Cache() { - _entries = new Dictionary(); + _entries = new ConcurrentDictionary(); } public TResult Get(TKey key, Func, TResult> acquire) { - CacheEntry entry; - if (!_entries.TryGetValue(key, out entry) || entry.Tokens.Any(t => !t.IsCurrent)) { - entry = new CacheEntry { Tokens = new List() }; - - var context = new AcquireContext(key, volatileItem => entry.Tokens.Add(volatileItem)); - entry.Result = acquire(context); - _entries[key] = entry; - } + var entry = _entries.AddOrUpdate(key, + // "Add" lambda + k => CreateEntry(k, acquire), + // "Update" lamdba + (k, currentEntry) => (currentEntry.Tokens.All(t => t.IsCurrent) ? currentEntry : CreateEntry(k, acquire))); return entry.Result; } + private static CacheEntry CreateEntry(TKey k, Func, TResult> acquire) { + var entry = new CacheEntry { Tokens = new List() }; + var context = new AcquireContext(k, volatileItem => entry.Tokens.Add(volatileItem)); + entry.Result = acquire(context); + return entry; + } + private class CacheEntry { public TResult Result { get; set; } public IList Tokens { get; set; } } } - }