public async Task GetOrCreateAsync()

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));
        }