119 lines
4.1 KiB
C#
119 lines
4.1 KiB
C#
// ==++==
|
|
//
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
//
|
|
// ==--==
|
|
|
|
namespace System.Runtime.InteropServices
|
|
{
|
|
using System;
|
|
using System.Threading;
|
|
|
|
public sealed class HandleCollector {
|
|
private const int deltaPercent = 10; // this is used for increasing the threshold.
|
|
private string name;
|
|
private int initialThreshold;
|
|
private int maximumThreshold;
|
|
private int threshold;
|
|
private int handleCount;
|
|
|
|
private int[] gc_counts = new int [3];
|
|
private int gc_gen = 0;
|
|
|
|
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("initialThreshold",
|
|
SR.GetString(SR.ArgumentOutOfRange_NeedNonNegNumRequired));
|
|
}
|
|
|
|
if( maximumThreshold < 0) {
|
|
throw new ArgumentOutOfRangeException("maximumThreshold",
|
|
SR.GetString(SR.ArgumentOutOfRange_NeedNonNegNumRequired));
|
|
}
|
|
|
|
if( initialThreshold > maximumThreshold) {
|
|
throw new ArgumentException(SR.GetString(SR.Argument_InvalidThreshold));
|
|
}
|
|
|
|
if ( name != null) {
|
|
this.name = name;
|
|
}
|
|
else {
|
|
this.name = String.Empty;
|
|
}
|
|
|
|
this.initialThreshold = initialThreshold;
|
|
this.maximumThreshold = maximumThreshold ;
|
|
this.threshold = initialThreshold;
|
|
this.handleCount = 0;
|
|
}
|
|
|
|
public int Count { get {return handleCount;} }
|
|
|
|
public int InitialThreshold { get { return initialThreshold;} }
|
|
|
|
public int MaximumThreshold { get { return maximumThreshold;} }
|
|
|
|
public string Name { get {return name;} }
|
|
|
|
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Reliability", "CA2001:AvoidCallingProblematicMethods")] // Keep call to GC.Collect()
|
|
public void Add () {
|
|
int gen_collect = -1;
|
|
Interlocked.Increment( ref handleCount);
|
|
if( handleCount < 0) {
|
|
throw new InvalidOperationException(SR.GetString(SR.InvalidOperation_HCCountOverflow));
|
|
}
|
|
|
|
if (handleCount > threshold) {
|
|
lock (this) {
|
|
threshold = handleCount + (handleCount/deltaPercent);
|
|
gen_collect = gc_gen;
|
|
if (gc_gen < 2) {
|
|
gc_gen++;
|
|
}
|
|
}
|
|
}
|
|
|
|
if ((gen_collect >= 0) &&
|
|
((gen_collect == 0) ||
|
|
(gc_counts[gen_collect] == GC.CollectionCount (gen_collect)))) {
|
|
GC.Collect (gen_collect);
|
|
Thread.Sleep (10*gen_collect);
|
|
}
|
|
|
|
//don't bother with gen0.
|
|
for (int i = 1; i < 3; i++) {
|
|
gc_counts [i] = GC.CollectionCount (i);
|
|
}
|
|
}
|
|
|
|
public void Remove () {
|
|
Interlocked.Decrement( ref handleCount);
|
|
if (handleCount < 0) {
|
|
throw new InvalidOperationException(SR.GetString(SR.InvalidOperation_HCCountOverflow));
|
|
}
|
|
|
|
int newThreshold = handleCount + handleCount/deltaPercent;
|
|
if (newThreshold < (threshold - threshold/deltaPercent)) {
|
|
lock( this) {
|
|
if (newThreshold > initialThreshold) {
|
|
threshold = newThreshold;
|
|
}
|
|
else {
|
|
threshold = initialThreshold;
|
|
}
|
|
gc_gen = 0;
|
|
}
|
|
}
|
|
|
|
for (int i = 1; i < 3; i++) {
|
|
gc_counts [i] = GC.CollectionCount (i);
|
|
}
|
|
}
|
|
}
|
|
}
|