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(); }
+ }
+}