mirror of
https://github.com/OrchardCMS/Orchard.git
synced 2025-10-14 19:04:51 +08:00
Fix concurrency issue accessing Dictionary instance
--HG-- branch : dev
This commit is contained in:
@@ -1,31 +1,35 @@
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace Orchard.Caching {
|
||||
public class Cache<TKey, TResult> : ICache<TKey, TResult> {
|
||||
private readonly Dictionary<TKey, CacheEntry> _entries;
|
||||
private readonly ConcurrentDictionary<TKey, CacheEntry> _entries;
|
||||
|
||||
public Cache() {
|
||||
_entries = new Dictionary<TKey, CacheEntry>();
|
||||
_entries = new ConcurrentDictionary<TKey, CacheEntry>();
|
||||
}
|
||||
|
||||
public TResult Get(TKey key, Func<AcquireContext<TKey>, TResult> acquire) {
|
||||
CacheEntry entry;
|
||||
if (!_entries.TryGetValue(key, out entry) || entry.Tokens.Any(t => !t.IsCurrent)) {
|
||||
entry = new CacheEntry { Tokens = new List<IVolatileToken>() };
|
||||
|
||||
var context = new AcquireContext<TKey>(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<AcquireContext<TKey>, TResult> acquire) {
|
||||
var entry = new CacheEntry { Tokens = new List<IVolatileToken>() };
|
||||
var context = new AcquireContext<TKey>(k, volatileItem => entry.Tokens.Add(volatileItem));
|
||||
entry.Result = acquire(context);
|
||||
return entry;
|
||||
}
|
||||
|
||||
private class CacheEntry {
|
||||
public TResult Result { get; set; }
|
||||
public IList<IVolatileToken> Tokens { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
Reference in New Issue
Block a user