/
githubmirror
/
roslyn
Обзор
Документация
Войти
/
githubmirror
/
roslyn
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
src/RoslynAnalyzers/Utilities/FlowAnalysis/SingleThreadedConcurrentDictionary.cs
70 строк
3 KB
Joey Robichaud
Fix file headers
15 мар 2025, 02:53
15 мар 2025, 02:53
e56be3a
Код
Авторство
О чём код?
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. using System; using System.Collections.Concurrent; namespace Analyzer.Utilities { /// <summary> /// Like ConcurrentDictionary, but single threaded valueFactory execution in GetOrAdd. /// </summary> /// <remarks>Useful for long running valueFactory functions, like say performing /// dataflow analysis. This way DFA is invoked only once per key, even if multiple /// threads simultaneously request the same key.</remarks> #pragma warning disable CA1812 // SingleThreadedConcurrentDictionary is too used. internal sealed class SingleThreadedConcurrentDictionary<TKey, TValue> where TValue : class #pragma warning restore CA1812 { /// <summary> /// An Entry itself serves a lock object, and contains the real value. /// </summary> private sealed class Entry { public TValue? Value { get; set; } } /// <summary> /// Holds entries, which contain the actual values. /// </summary> private readonly ConcurrentDictionary<TKey, Entry> BackingDictionary = new(); /// <summary> /// Adds a key/value pair using the specified function if the key does not already exist. Returns the new value, or the existing value if the key exists. /// </summary> /// <param name="key">Key to add.</param> /// <param name="valueFactory">Function to be invoked to generate the key, if necessary.</param> /// <returns>Value of the key, which will either be the existing value, or new value if the key was not in the dictionary.</returns> public TValue? GetOrAdd(TKey key, Func<TKey, TValue?> valueFactory) { if (key == null) { throw new ArgumentNullException(nameof(key)); } if (valueFactory == null) { throw new ArgumentNullException(nameof(valueFactory)); } // The return value of ConcurrentDictionary.GetOrAdd() is // consistent, i.e. the same instance no matter how many times // this valueFactory gets executed. So for a given key, we'll // always get back the same Entry instance. Entry entry = this.BackingDictionary.GetOrAdd(key, (_) => new Entry()); if (entry.Value != null) { return entry.Value; } lock (entry) { entry.Value ??= valueFactory(key); } return entry.Value; } } }