| File: System\Runtime\BackoffTimeoutHelper.cs | Web Access |
| Project: src\src\System.ServiceModel.NetNamedPipe\src\System.ServiceModel.NetNamedPipe.csproj (System.ServiceModel.NetNamedPipe) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System.Threading.Tasks; namespace System.Runtime { internal sealed class BackoffTimeoutHelper { private static readonly int s_maxSkewMilliseconds = 15; private static readonly long s_maxDriftTicks = s_maxSkewMilliseconds * TimeSpan.TicksPerMillisecond * 2; private static readonly TimeSpan s_defaultInitialWaitTime = TimeSpan.FromMilliseconds(1); private static readonly TimeSpan s_defaultMaxWaitTime = TimeSpan.FromMinutes(1); private DateTime _deadline; private readonly TimeSpan _maxWaitTime; private TimeSpan _waitTime; private readonly Random _random; internal BackoffTimeoutHelper(TimeSpan timeout) : this(timeout, s_defaultMaxWaitTime) { } internal BackoffTimeoutHelper(TimeSpan timeout, TimeSpan maxWaitTime) : this(timeout, maxWaitTime, s_defaultInitialWaitTime) { } internal BackoffTimeoutHelper(TimeSpan timeout, TimeSpan maxWaitTime, TimeSpan initialWaitTime) { _random = new Random(GetHashCode()); _maxWaitTime = maxWaitTime; OriginalTimeout = timeout; Reset(timeout, initialWaitTime); } public TimeSpan OriginalTimeout { get; } private void Reset(TimeSpan timeout, TimeSpan initialWaitTime) { if (timeout == TimeSpan.MaxValue) { _deadline = DateTime.MaxValue; } else { _deadline = DateTime.UtcNow + timeout; } _waitTime = initialWaitTime; } public bool IsExpired() { if (_deadline == DateTime.MaxValue) { return false; } else { return (DateTime.UtcNow >= _deadline); } } public async Task WaitAndBackoffAsync() { await Task.Delay(WaitTimeWithDrift()); Backoff(); } private TimeSpan WaitTimeWithDrift() { return Ticks.ToTimeSpan(Math.Max( Ticks.FromTimeSpan(s_defaultInitialWaitTime), Ticks.Add(Ticks.FromTimeSpan(_waitTime), (uint)_random.Next() % (2 * BackoffTimeoutHelper.s_maxDriftTicks + 1) - s_maxDriftTicks))); } private void Backoff() { if (_waitTime.Ticks >= (_maxWaitTime.Ticks / 2)) { _waitTime = _maxWaitTime; } else { _waitTime = TimeSpan.FromTicks(_waitTime.Ticks * 2); } if (_deadline != DateTime.MaxValue) { TimeSpan remainingTime = _deadline - DateTime.UtcNow; if (_waitTime > remainingTime) { _waitTime = remainingTime; if (_waitTime < TimeSpan.Zero) { _waitTime = TimeSpan.Zero; } } } } } }