CancellationTokenSourcePool
using System;
using System.Runtime.CompilerServices;
using System.Threading;
using System.Threading.Tasks;
namespace Polly.Utils
{
[System.Runtime.CompilerServices.NullableContext(1)]
[System.Runtime.CompilerServices.Nullable(0)]
internal abstract class CancellationTokenSourcePool
{
[System.Runtime.CompilerServices.Nullable(0)]
private sealed class DisposableCancellationTokenSourcePool : CancellationTokenSourcePool
{
private readonly TimeProvider _timeProvider;
public DisposableCancellationTokenSourcePool(TimeProvider timeProvider)
{
_timeProvider = timeProvider;
}
protected override CancellationTokenSource GetCore(TimeSpan delay)
{
if (!IsCancellable(delay))
return new CancellationTokenSource();
return TimeProviderTaskExtensions.CreateCancellationTokenSource(_timeProvider, delay);
}
public override void Return(CancellationTokenSource source)
{
source.Dispose();
}
}
[System.Runtime.CompilerServices.Nullable(0)]
private sealed class PooledCancellationTokenSourcePool : CancellationTokenSourcePool
{
public static readonly PooledCancellationTokenSourcePool SystemInstance = new PooledCancellationTokenSourcePool(TimeProvider.get_System());
private readonly ObjectPool<CancellationTokenSource> _pool;
public PooledCancellationTokenSourcePool(TimeProvider timeProvider)
{
_pool = new ObjectPool<CancellationTokenSource>(() => new CancellationTokenSource(), (CancellationTokenSource cts) => true);
}
protected override CancellationTokenSource GetCore(TimeSpan delay)
{
CancellationTokenSource cancellationTokenSource = _pool.Get();
if (IsCancellable(delay))
cancellationTokenSource.CancelAfter(delay);
return cancellationTokenSource;
}
public override void Return(CancellationTokenSource source)
{
if (source.TryReset())
_pool.Return(source);
else
source.Dispose();
}
}
public static CancellationTokenSourcePool Create(TimeProvider timeProvider)
{
if ((object)timeProvider == (object)TimeProvider.get_System())
return PooledCancellationTokenSourcePool.SystemInstance;
return new DisposableCancellationTokenSourcePool(timeProvider);
}
public CancellationTokenSource Get(TimeSpan delay)
{
if (delay <= TimeSpan.Zero && delay != System.Threading.Timeout.InfiniteTimeSpan)
throw new ArgumentOutOfRangeException("delay", delay, "Invalid delay specified.");
return GetCore(delay);
}
protected abstract CancellationTokenSource GetCore(TimeSpan delay);
public abstract void Return(CancellationTokenSource source);
protected static bool IsCancellable(TimeSpan delay)
{
return delay != System.Threading.Timeout.InfiniteTimeSpan;
}
}
}