| File: src\aspnetcore\src\Shared\Buffers.MemoryPool\DefaultMemoryPoolFactory.cs | Web Access |
| Project: src\aspnetcore\src\Servers\IIS\IIS\src\Microsoft.AspNetCore.Server.IIS.csproj (Microsoft.AspNetCore.Server.IIS) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System.Buffers; using System.Collections.Concurrent; using System.Diagnostics; using System.Diagnostics.Metrics; using Microsoft.AspNetCore.Connections; using Microsoft.Extensions.Logging; namespace Microsoft.AspNetCore; #nullable enable internal sealed class DefaultMemoryPoolFactory : IMemoryPoolFactory<byte>, IAsyncDisposable { private readonly MemoryPoolMetrics? _metrics; private readonly ConcurrentDictionary<PinnedBlockMemoryPool, bool> _pools = new(); private readonly PeriodicTimer _timer; private readonly Task _timerTask; private readonly ILogger? _logger; public DefaultMemoryPoolFactory(MemoryPoolMetrics? metrics = null, ILogger<DefaultMemoryPoolFactory>? logger = null) { _metrics = metrics; _logger = logger; _timer = new PeriodicTimer(PinnedBlockMemoryPool.DefaultEvictionDelay); _timerTask = Task.Run(async () => { try { while (await _timer.WaitForNextTickAsync()) { foreach (var pool in _pools.Keys) { pool.PerformEviction(); } } } catch (Exception ex) { _logger?.LogCritical(ex, "Error while evicting memory from pools."); } }); } public MemoryPool<byte> Create(MemoryPoolOptions? options = null) { var pool = new PinnedBlockMemoryPool(options?.Owner, _metrics, _logger); _pools.TryAdd(pool, true); pool.OnPoolDisposed(static (state, self) => { ((ConcurrentDictionary<PinnedBlockMemoryPool, bool>)state!).TryRemove(self, out _); }, _pools); return pool; } public async ValueTask DisposeAsync() { _timer.Dispose(); await _timerTask; } }