using System.Collections.Concurrent; namespace LightlessSync.Utils; public sealed class TaskRegistry where HandleType : notnull { private readonly ConcurrentDictionary _activeTasks = new(); public Task GetOrStart(HandleType handle, Func taskFactory) { ActiveTask entry = _activeTasks.GetOrAdd(handle, i => new ActiveTask(() => ExecuteAndRemove(i, taskFactory))); return entry.EnsureStarted(); } public Task GetOrStart(HandleType handle, Func> taskFactory) { ActiveTask entry = _activeTasks.GetOrAdd(handle, i => new ActiveTask(() => ExecuteAndRemove(i, taskFactory))); return (Task)entry.EnsureStarted(); } public bool TryGetExisting(HandleType handle, out Task task) { if (_activeTasks.TryGetValue(handle, out ActiveTask? entry)) { task = entry.EnsureStarted(); return true; } task = Task.CompletedTask; return false; } private async Task ExecuteAndRemove(HandleType handle, Func taskFactory) { try { await taskFactory().ConfigureAwait(false); } finally { _activeTasks.TryRemove(handle, out _); } } private async Task ExecuteAndRemove(HandleType handle, Func> taskFactory) { try { return await taskFactory().ConfigureAwait(false); } finally { _activeTasks.TryRemove(handle, out _); } } private sealed class ActiveTask { private readonly object _gate = new(); private readonly Func _starter; private Task? _cached; public ActiveTask(Func starter) { _starter = starter; } public Task EnsureStarted() { lock (_gate) { if (_cached == null || _cached.IsCompleted) { _cached = _starter(); } return _cached; } } } }