Ayende @ Rahien

Hi!
My name is Ayende Rahien
Founder of Hibernating Rhinos LTD and RavenDB.
You can reach me by phone or email:

ayende@ayende.com

+972 52-548-6969

, @ Q c

Posts: 5,949 | Comments: 44,548

filter by tags archive

I love ConcurrentDictionary!


Not just because it is concurrent, because of this wonderful method:

public class Storage : IStorage
{
    private readonly ConcurrentDictionary<Guid, ConcurrentDictionary<int, List<object>>> values =
        new ConcurrentDictionary<Guid, ConcurrentDictionary<int, List<object>>>();

    public void Store(Guid taskId, int level, object value)
    {
        values.GetOrAdd(taskId, guid => new ConcurrentDictionary<int, List<object>>())
            .GetOrAdd(level, i => new List<object>())
            .Add(value);
    }
}

Doing this with Dictionary is always a pain, but this is an extremely natural way of doing things.


Comments

Tommy Carlier

That's awesome. You could do this with regular dictionaries, by adding an extension method to IDictionary <tkey,> , like this:

static TValue GetOrAdd <tkey,> (this IDictionary <tkey,> collection, TKey key, Func <tkey,> generator)

{

TValue value;

if (!collection.TryGetValue(key, out value))

collection.Add(key, value = generator(key));

return value;

}

Tommy Carlier

Your commenting system apparently doesn't escape less-than and greater-than. Second attempt:

static TValue GetOrAdd<TKey, TValue>(this IDictionary<TKey, TValue> collection, TKey key, Func<TKey, TValue> generator)

{

TValue value;

if (!collection.TryGetValue(key, out value))

collection.Add(key, value = generator(key));

return value;

}

Torkel

That is a pretty useful function!

Dam, why did I not think of writing one like that. I do have a similar one I use for caches.

For example:

return cache.GetWithAdd("admembers", () => GetADMemberListRemote());

Paul Hatcher

You'd need some form of locking to make it thread safe, e.g.

TValue value;

lock (collection)

{

if (!collection.TryGetValue(key, out value))

collection.Add(key, value = generator(key));

}

return value;

And of course this doesn't preclude someone bypassing the lock by directly doing collection.Add

Robert Byrne

Yea some of the first extension methods I wrote were to deal with dictionaries. If theres nothing special about the way you construct the value, you can simplify slightly:

public static TValue GetOrAddDefaultValue<TKey, TValue>(this IDictionary<TKey, TValue> dictionary, TKey key) {

if (dictionary == null) return default(TValue);


TValue value = default(TValue);

bool exists = dictionary.TryGetValue(key, out value);


if (!exists) {

    if (typeof(TValue).IsValueType) {

        dictionary[key] = value;

    }

    else {

        value = Activator.CreateInstance<TValue>();

        dictionary[key] = value;

    }

}


return value;

}

configurator

Shouldn't you use some concurrent datatype for the list as well?

tobi

Although it is beside your point you use a single dictionary with a tuple as the key.

Comment preview

Comments have been closed on this topic.

FUTURE POSTS

No future posts left, oh my!

RECENT SERIES

  1. The RavenDB Comic Strip (3):
    28 May 2015 - Part III – High availability & sleeping soundly
  2. Special Offer (2):
    27 May 2015 - 29% discount for all our products
  3. RavenDB Sharding (3):
    22 May 2015 - Adding a new shard to an existing cluster, splitting the shard
  4. Challenge (45):
    28 Apr 2015 - What is the meaning of this change?
  5. Interview question (2):
    30 Mar 2015 - fix the index
View all series

RECENT COMMENTS

Syndication

Main feed Feed Stats
Comments feed   Comments Feed Stats