Last active
September 6, 2022 02:29
-
-
Save StephenCleary/6c258078afe4242e0b3aee28f5c634b0 to your computer and use it in GitHub Desktop.
Cache for reusing CTS instances.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System.Collections.Concurrent; | |
using System.Diagnostics; | |
using Nito.Disposables; | |
/// <summary> | |
/// A cache of uncanceled <see cref="CancellationTokenSource"/> instances. | |
/// </summary> | |
public sealed class CancellationTokenSourceCache | |
{ | |
private readonly ConcurrentBag<CancellationTokenSource> _sources = new(); | |
public static CancellationTokenSourceCache Instance { get; } = new(); | |
/// <summary> | |
/// Retrieves a CTS from the cache, or creates a new one if the cache is empty. | |
/// </summary> | |
public CachedCancellationTokenSource Allocate() => new(this, _sources.TryTake(out var result) ? result : new CancellationTokenSource()); | |
/// <summary> | |
/// A CTS wrapper that, when disposed, returns the CTS to the cache if it is not canceled. | |
/// </summary> | |
public sealed class CachedCancellationTokenSource : SingleNonblockingDisposable<CancellationTokenSourceCache?> | |
{ | |
private readonly CancellationTokenSource _source; | |
public CachedCancellationTokenSource(CancellationTokenSourceCache cache, CancellationTokenSource source) | |
: base(cache) | |
{ | |
_source = source; | |
} | |
/// <summary> | |
/// Cancels the CTS. When disposed, this instance will dispose the CTS instead of returning it to the cache. | |
/// </summary> | |
public void Cancel() | |
{ | |
if (TryUpdateContext(_ => null)) | |
_source.Cancel(); | |
} | |
protected override void Dispose(CancellationTokenSourceCache? context) | |
{ | |
if (context == null) | |
{ | |
_source.Dispose(); | |
return; | |
} | |
Debug.Assert(!_source.IsCancellationRequested); | |
context._sources.Add(_source); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Note: caching CTSs (and reusing CTSs in general) assumes that any CT registrations are disposed when their operation completes without being canceled.