Ayende @ Rahien

Hi!
My name is Oren Eini
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,969 | Comments: 44,491

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. Production postmortem (5):
    29 Jul 2015 - The evil licensing code
  2. Career planning (6):
    24 Jul 2015 - The immortal choices aren't
  3. API Design (7):
    20 Jul 2015 - We’ll let the users sort it out
  4. What is new in RavenDB 3.5 (3):
    15 Jul 2015 - Exploring data in the dark
  5. The RavenDB Comic Strip (3):
    28 May 2015 - Part III – High availability & sleeping soundly
View all series

RECENT COMMENTS

Syndication

Main feed Feed Stats
Comments feed   Comments Feed Stats