Skip to content

Instantly share code, notes, and snippets.

@theodorzoulias
Last active May 3, 2022 08:59
Show Gist options
  • Save theodorzoulias/cdda43132b61cccd19d202361df1245e to your computer and use it in GitHub Desktop.
Save theodorzoulias/cdda43132b61cccd19d202361df1245e to your computer and use it in GitHub Desktop.
TryUpdateOrRemove extension method -- https://stackoverflow.com/a/72063401/11178549
using System;
using System.Collections;
using System.Collections.Concurrent;
using System.Collections.Generic;
public static class ConcurrentDictionaryExtensions
{
/// <summary>
/// Uses the specified function to update a key/collection pair in the dictionary,
/// if the key already exists. In case the function returns a null or empty
/// collection, the key/collection pair is removed from the dictionary.
/// In case the function returns the existing collection, the result is false.
/// </summary>
public static bool TryUpdateOrRemove<TKey, TCollection>(
this ConcurrentDictionary<TKey, TCollection> source, TKey key,
Func<TKey, TCollection, TCollection> updateValueFactory)
where TCollection : class, ICollection
{
while (true)
{
if (!source.TryGetValue(key, out var existing))
return false;
var updated = updateValueFactory(key, existing);
if (ReferenceEquals(updated, existing)) return false;
if (updated is null || updated.Count == 0)
{
if (source.TryRemove(KeyValuePair.Create(key, existing))) return true;
}
else
{
if (source.TryUpdate(key, updated, existing)) return true;
}
// We lost the race to either TryRemove or TryUpdate. Try again.
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment