Alternative to ConcurrentDictionary for portable class library
I'm writing a portable class library that targets .NET 4.5, Windows Store
apps and Windows Phone 8. I need an efficient in-memory cache mechanism,
so I was thinking about using ConcurrentDictionary<K,V>, but it's not
available in WP8.
There will be many reads and relatively few writes, so ideally I'd like a
collection that supports lock-free reads from multiple threads, and write
by a single thread. The non-generic Hashtable has that property, according
to MSDN, but unfortunately it's not available in the PCL...
Is there another collection class available in the PCL that matches this
requirement? If not, what would be a good way to achieve thread safety
without locking for reads? (locking for writes is OK, since it won't
happen too often)
EDIT: thanks to JaredPar's guidance, I eventually implemented my cache in
a completely lock-free fashion, using ImmutableDictionary<TKey, TValue>
from Microsoft.Bcl.Immutable:
class Cache<TKey, TValue>
{
private IImmutableDictionary<TKey, TValue> _cache =
ImmutableDictionary.Create<TKey, TValue>();
public TValue GetOrAdd(TKey key, [NotNull] Func<TKey, TValue>
valueFactory)
{
valueFactory.CheckArgumentNull("valueFactory");
TValue newValue = default(TValue);
bool newValueCreated = false;
while (true)
{
var oldCache = _cache;
TValue value;
if (oldCache.TryGetValue(key, out value))
return value;
// Value not found; create it if necessary
if (!newValueCreated)
{
newValue = valueFactory(key);
newValueCreated = true;
}
// Add the new value to the cache
var newCache = oldCache.Add(key, newValue);
if (Interlocked.CompareExchange(ref _cache, newCache,
oldCache) == oldCache)
{
// Cache successfully written
return newValue;
}
// Failed to write the new cache because another thread
// already changed it; try again.
}
}
public void Clear()
{
_cache = _cache.Clear();
}
}
No comments:
Post a Comment