in src/Fx/Singleton.cs [152:204]
public async Task<TValue> GetOrCreateAsync(TimeSpan timeout, CancellationToken cancellationToken)
{
TimeoutHelper timeoutHelper = new TimeoutHelper(timeout);
while (timeoutHelper.RemainingTime() > TimeSpan.Zero)
{
if (cancellationToken.IsCancellationRequested)
{
throw new TaskCanceledException();
}
if (this.disposed)
{
throw new ObjectDisposedException(this.GetType().Name);
}
TaskCompletionSource<TValue> tcs;
if (this.TryGet(out tcs))
{
TValue current = await tcs.Task.ConfigureAwait(false);
if (this.IsValid(current))
{
return current;
}
this.Invalidate(current);
}
tcs = new TaskCompletionSource<TValue>(TaskCreationOptions.RunContinuationsAsynchronously);
if (this.TrySet(tcs))
{
try
{
TValue value = await this.OnCreateAsync(timeoutHelper.RemainingTime(), cancellationToken).ConfigureAwait(false);
tcs.SetResult(value);
if (this.disposed && this.TryRemove())
{
OnSafeClose(value);
}
}
catch (Exception ex) when (!Fx.IsFatal(ex))
{
this.TryRemove();
tcs.SetException(ex);
}
return await tcs.Task.ConfigureAwait(false);
}
}
throw new TimeoutException(AmqpResources.GetString(AmqpResources.AmqpTimeout, timeout, typeof(TValue).Name));
}