The Labs \ Source Viewer \ SSCLI \ System.Runtime.InteropServices \ HandleCollector

  1. // ==++==
  2. //
  3. //
  4. // Copyright (c) 2006 Microsoft Corporation. All rights reserved.
  5. //
  6. // The use and distribution terms for this software are contained in the file
  7. // named license.txt, which can be found in the root of this distribution.
  8. // By using this software in any fashion, you are agreeing to be bound by the
  9. // terms of this license.
  10. //
  11. // You must not remove this notice, or any other, from this software.
  12. //
  13. //
  14. // ==--==
  15. namespace System.Runtime.InteropServices
  16. {
  17.     using System;
  18.     using System.Threading;
  19.    
  20.     public sealed class HandleCollector
  21.     {
  22.         private const int deltaPercent = 10;
  23.         // this is used for increasing the threshold.
  24.         private string name;
  25.         private int initialThreshold;
  26.         private int maximumThreshold;
  27.         private int threshold;
  28.         private int handleCount;
  29.        
  30.         private int[] gc_counts = new int[3];
  31.         private int gc_gen = 0;
  32.        
  33.         public HandleCollector(string name, int initialThreshold) : this(name, initialThreshold, int.MaxValue)
  34.         {
  35.         }
  36.        
  37.         public HandleCollector(string name, int initialThreshold, int maximumThreshold)
  38.         {
  39.             if (initialThreshold < 0) {
  40.                 throw new ArgumentOutOfRangeException("initialThreshold", SR.GetString(SR.ArgumentOutOfRange_NeedNonNegNumRequired));
  41.             }
  42.            
  43.             if (maximumThreshold < 0) {
  44.                 throw new ArgumentOutOfRangeException("maximumThreshold", SR.GetString(SR.ArgumentOutOfRange_NeedNonNegNumRequired));
  45.             }
  46.            
  47.             if (initialThreshold > maximumThreshold) {
  48.                 throw new ArgumentException(SR.GetString(SR.Argument_InvalidThreshold));
  49.             }
  50.            
  51.             if (name != null) {
  52.                 this.name = name;
  53.             }
  54.             else {
  55.                 this.name = String.Empty;
  56.             }
  57.            
  58.             this.initialThreshold = initialThreshold;
  59.             this.maximumThreshold = maximumThreshold;
  60.             this.threshold = initialThreshold;
  61.             this.handleCount = 0;
  62.         }
  63.        
  64.         public int Count {
  65.             get { return handleCount; }
  66.         }
  67.        
  68.         public int InitialThreshold {
  69.             get { return initialThreshold; }
  70.         }
  71.        
  72.         public int MaximumThreshold {
  73.             get { return maximumThreshold; }
  74.         }
  75.        
  76.         public string Name {
  77.             get { return name; }
  78.         }
  79.        
  80.         [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Reliability", "CA2001:AvoidCallingProblematicMethods")]
  81.         // Keep call to GC.Collect()
  82.         public void Add()
  83.         {
  84.             int gen_collect = -1;
  85.             Interlocked.Increment(ref handleCount);
  86.             if (handleCount < 0) {
  87.                 throw new InvalidOperationException(SR.GetString(SR.InvalidOperation_HCCountOverflow));
  88.             }
  89.            
  90.             if (handleCount > threshold) {
  91.                 lock (this) {
  92.                     threshold = handleCount + (handleCount / deltaPercent);
  93.                     gen_collect = gc_gen;
  94.                     if (gc_gen < 2) {
  95.                         gc_gen++;
  96.                     }
  97.                 }
  98.             }
  99.            
  100.             if ((gen_collect >= 0) && ((gen_collect == 0) || (gc_counts[gen_collect] == GC.CollectionCount(gen_collect)))) {
  101.                 GC.Collect(gen_collect);
  102.                 Thread.Sleep(10 * gen_collect);
  103.             }
  104.            
  105.             //don't bother with gen0.
  106.             for (int i = 1; i < 3; i++) {
  107.                 gc_counts[i] = GC.CollectionCount(i);
  108.             }
  109.         }
  110.        
  111.         public void Remove()
  112.         {
  113.             Interlocked.Decrement(ref handleCount);
  114.             if (handleCount < 0) {
  115.                 throw new InvalidOperationException(SR.GetString(SR.InvalidOperation_HCCountOverflow));
  116.             }
  117.            
  118.             int newThreshold = handleCount + handleCount / deltaPercent;
  119.             if (newThreshold < (threshold - threshold / deltaPercent)) {
  120.                 lock (this) {
  121.                     if (newThreshold > initialThreshold) {
  122.                         threshold = newThreshold;
  123.                     }
  124.                     else {
  125.                         threshold = initialThreshold;
  126.                     }
  127.                     gc_gen = 0;
  128.                 }
  129.             }
  130.            
  131.             for (int i = 1; i < 3; i++) {
  132.                 gc_counts[i] = GC.CollectionCount(i);
  133.             }
  134.         }
  135.     }
  136. }

Developer Fusion