| File: System\Runtime\InteropServices\HandleCollector.cs | Web Access |
| Project: src\runtime\src\libraries\System.Runtime.InteropServices\src\System.Runtime.InteropServices.csproj (System.Runtime.InteropServices) |
// 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; namespace System.Runtime.InteropServices { public sealed class HandleCollector { // Used for increasing the threshold. private const int DeltaPercent = 10; private int _threshold; private int _handleCount; private readonly int[] _gcCounts = new int[3]; private int _gcGeneration; public HandleCollector(string? name, int initialThreshold) : this(name, initialThreshold, int.MaxValue) { } public HandleCollector(string? name, int initialThreshold, int maximumThreshold) { if (initialThreshold < 0) { throw new ArgumentOutOfRangeException(nameof(initialThreshold), initialThreshold, SR.Arg_NeedNonNegNumRequired); } if (maximumThreshold < 0) { throw new ArgumentOutOfRangeException(nameof(maximumThreshold), maximumThreshold, SR.Arg_NeedNonNegNumRequired); } if (initialThreshold > maximumThreshold) { throw new ArgumentException(SR.Arg_InvalidThreshold, nameof(initialThreshold)); } Name = name ?? string.Empty; InitialThreshold = initialThreshold; MaximumThreshold = maximumThreshold; _threshold = initialThreshold; _handleCount = 0; _gcGeneration = 0; } public int Count => _handleCount; public int InitialThreshold { get; } public int MaximumThreshold { get; } public string Name { get; } public void Add() { int collectionGeneration = -1; Interlocked.Increment(ref _handleCount); if (_handleCount < 0) { throw new InvalidOperationException(SR.InvalidOperation_HCCountOverflow); } if (_handleCount > _threshold) { lock (this) { _threshold = _handleCount + (_handleCount / DeltaPercent); collectionGeneration = _gcGeneration; if (_gcGeneration < 2) { _gcGeneration++; } } } if ((collectionGeneration >= 0) && ((collectionGeneration == 0) || (_gcCounts[collectionGeneration] == GC.CollectionCount(collectionGeneration)))) { GC.Collect(collectionGeneration); Thread.Sleep(10 * collectionGeneration); } // Don't bother with gen0. for (int i = 1; i < 3; i++) { _gcCounts[i] = GC.CollectionCount(i); } } public void Remove() { Interlocked.Decrement(ref _handleCount); if (_handleCount < 0) { throw new InvalidOperationException(SR.InvalidOperation_HCCountOverflow); } int newThreshold = _handleCount + _handleCount / DeltaPercent; if (newThreshold < (_threshold - _threshold / DeltaPercent)) { lock (this) { if (newThreshold > InitialThreshold) { _threshold = newThreshold; } else { _threshold = InitialThreshold; } _gcGeneration = 0; } } for (int i = 1; i < 3; i++) { _gcCounts[i] = GC.CollectionCount(i); } } } }