private void Remove(InnerHandler handler)
            {
                for (; ;)
                {
                    var a = Volatile.Read(ref _inners);
                    var n = a.Length;
                    if (n == 0)
                    {
                        break;
                    }
                    var idx = Array.IndexOf(a, handler);
                    if (idx < 0)
                    {
                        break;
                    }
                    InnerHandler[] b;
                    if (n == 1)
                    {
                        b = Empty;
                    }
                    else
                    {
                        b = new InnerHandler[n - 1];
                        Array.Copy(a, 0, b, 0, idx);
                        Array.Copy(a, idx + 1, b, idx, n - idx - 1);
                    }

                    if (Interlocked.CompareExchange(ref _inners, b, a) == a)
                    {
                        handler.Dispose();
                        break;
                    }
                }
            }
            private void NextHandler(Task <bool> t)
            {
                if (t.IsFaulted)
                {
                    ExceptionHelper.AddException(ref _error, ExceptionHelper.Extract(t.Exception));
                    _done = true;
                    if (TryDispose())
                    {
                        Signal();
                    }
                }
                else if (t.Result)
                {
                    IAsyncEnumerator <TResult> src;
                    try
                    {
                        src = _mapper(_source.Current).GetAsyncEnumerator();
                    }
                    catch (Exception ex)
                    {
                        ExceptionHelper.AddException(ref _error, ex);
                        _done = true;
                        Dispose(_source);
                        Signal();
                        return;
                    }

                    if (TryDispose())
                    {
                        Interlocked.Increment(ref _allDisposeWip);
                        var inner = new InnerHandler(src, this);

                        for (; ;)
                        {
                            var curr = Volatile.Read(ref _current);
                            if (curr == DisposedInnerHandler)
                            {
                                inner.Dispose();
                                break;
                            }
                            if (Interlocked.CompareExchange(ref _current, inner, curr) == curr)
                            {
                                curr?.Dispose();
                                inner.MoveNext();
                                MoveNext();
                                return;
                            }
                        }
                    }
                }
                else
                {
                    _done = true;
                    if (TryDispose())
                    {
                        Signal();
                    }
                }
            }
        protected override void Dispose(bool disposing)
        {
            base.Dispose(disposing);

            if (disposing && ownsHandler)
            {
                InnerHandler.Dispose();
            }
        }
        // ReSharper restore ExplicitCallerInfoArgument

        /// <summary>
        /// Releases the unmanaged resources used by the <see cref="T:System.Net.Http.DelegatingHandler" />, and optionally disposes of the managed resources.
        /// </summary>
        /// <param name="disposing">true to release both managed and unmanaged resources; false to releases only unmanaged resources.</param>
        protected override void Dispose(bool disposing)
        {
            if (disposing && Interlocked.CompareExchange(ref _disposeInner, 0, 1) == 1)
            {
                InnerHandler.Dispose();
            }

            base.Dispose(disposing);
        }
        private void CreateNewTransportHandler()
        {
            if (InnerHandler != null)
            {
                InnerHandler.Dispose();
                InnerHandler = null;
            }

            // Ask the ContinuationFactory to attach the proper handler given the Context's ITransportSettings.
            InnerHandler = ContinuationFactory(Context, null);
        }
Example #6
0
        public override async Task OpenAsync(TimeoutHelper timeoutHelper)
        {
            try
            {
                if (Logging.IsEnabled)
                {
                    Logging.Enter(this, timeoutHelper, $"{nameof(ProtocolRoutingDelegatingHandler)}.{nameof(OpenAsync)}");
                }

                bool gain = await _handlerLock.WaitAsync(timeoutHelper.GetRemainingTime()).ConfigureAwait(false);

                if (!gain)
                {
                    throw new TimeoutException("Timed out to acquire handler lock.");
                }

                SelectTransport();

                try
                {
                    CreateNewTransportIfNotReady();
                    await base.OpenAsync(timeoutHelper).ConfigureAwait(false);

                    // since Dispose is not synced with _handlerLock, double check if disposed.
                    if (_disposed)
                    {
                        InnerHandler?.Dispose();
                        ThrowIfDisposed();
                    }
                    _transportSelectionComplete = true;
                }
                finally
                {
                    _handlerLock.Release();
                }
            }
            finally
            {
                if (Logging.IsEnabled)
                {
                    Logging.Exit(this, timeoutHelper, $"{nameof(ProtocolRoutingDelegatingHandler)}.{nameof(OpenAsync)}");
                }
            }
        }
Example #7
0
        public override async Task OpenAsync(CancellationToken cancellationToken)
        {
            try
            {
                if (Logging.IsEnabled)
                {
                    Logging.Enter(this, cancellationToken, $"{nameof(ProtocolRoutingDelegatingHandler)}.{nameof(OpenAsync)}");
                }

                cancellationToken.ThrowIfCancellationRequested();
                await _handlerLock.WaitAsync(cancellationToken).ConfigureAwait(false);

                SelectTransport();

                try
                {
                    CreateNewTransportIfNotReady();
                    await base.OpenAsync(cancellationToken).ConfigureAwait(false);

                    // since Dispose is not synced with _handlerLock, double check if disposed.
                    if (_disposed)
                    {
                        InnerHandler?.Dispose();
                        ThrowIfDisposed();
                    }
                    _transportSelectionComplete = true;
                }
                finally
                {
                    _handlerLock.Release();
                }
            }
            finally
            {
                if (Logging.IsEnabled)
                {
                    Logging.Exit(this, cancellationToken, $"{nameof(ProtocolRoutingDelegatingHandler)}.{nameof(OpenAsync)}");
                }
            }
        }
        public override async Task OpenAsync(CancellationToken cancellationToken)
        {
            try
            {
                if (Logging.IsEnabled)
                {
                    Logging.Enter(this, cancellationToken, $"{nameof(ProtocolRoutingDelegatingHandler)}.{nameof(OpenAsync)}");
                }
                cancellationToken.ThrowIfCancellationRequested();

                await _handlerLock.WaitAsync().ConfigureAwait(false);

                if (!_transportSelectionComplete)
                {
                    // Try next protocol if we're still searching.

                    ITransportSettings[] transportSettingsArray = this.Context.Get <ITransportSettings[]>();
                    Debug.Assert(transportSettingsArray != null);

                    // Keep cycling through all transports until we find one that works.
                    if (_nextTransportIndex >= transportSettingsArray.Length)
                    {
                        _nextTransportIndex = 0;
                    }

                    ITransportSettings transportSettings = transportSettingsArray[_nextTransportIndex];
                    Debug.Assert(transportSettings != null);

                    if (Logging.IsEnabled)
                    {
                        Logging.Info(
                            this,
                            $"Trying {transportSettings?.GetTransportType()}",
                            $"{nameof(ProtocolRoutingDelegatingHandler)}.{nameof(OpenAsync)}");
                    }

                    // Configure the transportSettings for this context (Important! Within Context, 'ITransportSettings' != 'ITransportSettings[]').
                    Context.Set <ITransportSettings>(transportSettings);
                    CreateNewTransportHandler();

                    _nextTransportIndex++;
                }

                try
                {
                    CreateNewTransportIfNotReady();
                    await base.OpenAsync(cancellationToken).ConfigureAwait(false);

                    // since Dispose is not synced with _handlerLock, double check if disposed.
                    if (_disposed)
                    {
                        InnerHandler?.Dispose();
                        ThrowIfDisposed();
                    }
                    _transportSelectionComplete = true;
                }
                finally
                {
                    _handlerLock.Release();
                }
            }
            finally
            {
                if (Logging.IsEnabled)
                {
                    Logging.Exit(this, cancellationToken, $"{nameof(ProtocolRoutingDelegatingHandler)}.{nameof(OpenAsync)}");
                }
            }
        }