From 109ccbb0b064f8f6d54a98f228fa46b98f050da4 Mon Sep 17 00:00:00 2001 From: RoosterDragon Date: Thu, 9 Apr 2015 22:25:30 +0100 Subject: [PATCH] Added ConcurrentCache, a thread-safe Cache. --- OpenRA.Game/OpenRA.Game.csproj | 1 + OpenRA.Game/Primitives/Cache.cs | 12 ++---- OpenRA.Game/Primitives/ConcurrentCache.cs | 47 +++++++++++++++++++++++ 3 files changed, 51 insertions(+), 9 deletions(-) create mode 100644 OpenRA.Game/Primitives/ConcurrentCache.cs diff --git a/OpenRA.Game/OpenRA.Game.csproj b/OpenRA.Game/OpenRA.Game.csproj index f3bfb5ba67..033a547c5e 100644 --- a/OpenRA.Game/OpenRA.Game.csproj +++ b/OpenRA.Game/OpenRA.Game.csproj @@ -144,6 +144,7 @@ + diff --git a/OpenRA.Game/Primitives/Cache.cs b/OpenRA.Game/Primitives/Cache.cs index da285fb560..8daf43cd7c 100644 --- a/OpenRA.Game/Primitives/Cache.cs +++ b/OpenRA.Game/Primitives/Cache.cs @@ -9,7 +9,6 @@ #endregion using System; -using System.Collections; using System.Collections.Generic; namespace OpenRA.Primitives @@ -23,6 +22,7 @@ namespace OpenRA.Primitives { if (loader == null) throw new ArgumentNullException("loader"); + this.loader = loader; cache = new Dictionary(c); } @@ -32,13 +32,7 @@ namespace OpenRA.Primitives public U this[T key] { - get - { - U result; - if (!cache.TryGetValue(key, out result)) - cache.Add(key, result = loader(key)); - return result; - } + get { return cache.GetOrAdd(key, loader); } } public bool ContainsKey(T key) { return cache.ContainsKey(key); } @@ -47,6 +41,6 @@ namespace OpenRA.Primitives public ICollection Keys { get { return cache.Keys; } } public ICollection Values { get { return cache.Values; } } public IEnumerator> GetEnumerator() { return cache.GetEnumerator(); } - IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } + System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { return GetEnumerator(); } } } diff --git a/OpenRA.Game/Primitives/ConcurrentCache.cs b/OpenRA.Game/Primitives/ConcurrentCache.cs new file mode 100644 index 0000000000..f717548469 --- /dev/null +++ b/OpenRA.Game/Primitives/ConcurrentCache.cs @@ -0,0 +1,47 @@ +#region Copyright & License Information +/* + * Copyright 2007-2015 The OpenRA Developers (see AUTHORS) + * This file is part of OpenRA, which is free software. It is made + * available to you under the terms of the GNU General Public License + * as published by the Free Software Foundation. For more information, + * see COPYING. + */ +#endregion + +using System; +using System.Collections.Concurrent; +using System.Collections.Generic; + +namespace OpenRA.Primitives +{ + public class ConcurrentCache : IReadOnlyDictionary + { + readonly ConcurrentDictionary cache; + readonly Func loader; + + public ConcurrentCache(Func loader, IEqualityComparer c) + { + if (loader == null) + throw new ArgumentNullException("loader"); + + this.loader = loader; + cache = new ConcurrentDictionary(c); + } + + public ConcurrentCache(Func loader) + : this(loader, EqualityComparer.Default) { } + + public U this[T key] + { + get { return cache.GetOrAdd(key, loader); } + } + + public bool ContainsKey(T key) { return cache.ContainsKey(key); } + public bool TryGetValue(T key, out U value) { return cache.TryGetValue(key, out value); } + public int Count { get { return cache.Count; } } + public ICollection Keys { get { return cache.Keys; } } + public ICollection Values { get { return cache.Values; } } + public IEnumerator> GetEnumerator() { return cache.GetEnumerator(); } + System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { return GetEnumerator(); } + } +}