| File: ActiveHandlerTrackingEntry.cs | Web Access |
| Project: src\runtime\src\libraries\Microsoft.Extensions.Http\src\Microsoft.Extensions.Http.csproj (Microsoft.Extensions.Http) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System; using System.Diagnostics; using System.Threading; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Internal; namespace Microsoft.Extensions.Http { // Thread-safety: We treat this class as immutable except for the timer. Creating a new object // for the 'expiry' pool simplifies the threading requirements significantly. internal sealed class ActiveHandlerTrackingEntry { private static readonly TimerCallback _timerCallback = (s) => ((ActiveHandlerTrackingEntry)s!).Timer_Tick(); private readonly object _lock; private bool _timerInitialized; private Timer? _timer; private TimerCallback? _callback; public ActiveHandlerTrackingEntry( string name, LifetimeTrackingHttpMessageHandler handler, IServiceScope? scope, TimeSpan lifetime) { Name = name; Handler = handler; Scope = scope; Lifetime = lifetime; _lock = new object(); } public LifetimeTrackingHttpMessageHandler Handler { get; } public TimeSpan Lifetime { get; } public string Name { get; } public IServiceScope? Scope { get; } public void StartExpiryTimer(TimerCallback callback) { if (Lifetime == Timeout.InfiniteTimeSpan) { return; // never expires. } if (Volatile.Read(ref _timerInitialized)) { return; } StartExpiryTimerSlow(callback); } private void StartExpiryTimerSlow(TimerCallback callback) { Debug.Assert(Lifetime != Timeout.InfiniteTimeSpan); lock (_lock) { if (Volatile.Read(ref _timerInitialized)) { return; } _callback = callback; _timer = NonCapturingTimer.Create(_timerCallback, this, Lifetime, Timeout.InfiniteTimeSpan); _timerInitialized = true; } } private void Timer_Tick() { Debug.Assert(_callback != null); Debug.Assert(_timer != null); lock (_lock) { if (_timer != null) { _timer.Dispose(); _timer = null; _callback(this); } } } } }