using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Text.RegularExpressions; using System.Threading.Tasks; using Newtonsoft.Json; using WalletWasabi.Blockchain.TransactionOutputs; namespace BTCPayServer.Plugins.Wabisabi; public static class Extensions { public static string ToSentenceCase(this string str) { return Regex.Replace(str, "[a-z][A-Z]", m => m.Value[0] + " " + char.ToLower(m.Value[1])); } /// /// Returns an existing task from the concurrent dictionary, or adds a new task /// using the specified asynchronous factory method. Concurrent invocations for /// the same key are prevented, unless the task is removed before the completion /// of the delegate. Failed tasks are evicted from the concurrent dictionary. /// public static Task GetOrAddAsync( this ConcurrentDictionary> source, TKey key, Func> valueFactory) { if (!source.TryGetValue(key, out var currentTask)) { Task newTask = null; var newTaskTask = new Task>(async () => { try { return await valueFactory(key).ConfigureAwait(false); } catch { source.TryRemove(KeyValuePair.Create(key, newTask)); throw; } }); newTask = newTaskTask.Unwrap(); currentTask = source.GetOrAdd(key, newTask); if (currentTask == newTask) newTaskTask.Start(TaskScheduler.Default); } return currentTask; } }