Code:
/ Dotnetfx_Win7_3.5.1 / Dotnetfx_Win7_3.5.1 / 3.5.1 / DEVDIV / depot / DevDiv / releases / whidbey / NetFXspW7 / ndp / fx / src / Misc / HandleCollector.cs / 1 / HandleCollector.cs
#if DEBUG_HANDLECOLLECTOR using System.Diagnostics; #endif using System.Collections.Generic; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; [module: SuppressMessage("Microsoft.Design", "CA1020:AvoidNamespacesWithFewTypes", Scope="namespace", Target="System.Internal")] namespace System.Internal { internal sealed class HandleCollector { private static HandleType[] handleTypes; private static int handleTypeCount; private static int suspendCount; internal static event HandleChangeEventHandler HandleAdded; internal static event HandleChangeEventHandler HandleRemoved; private static object internalSyncObject = new object(); ////// /// Adds the given handle to the handle collector. This keeps the /// handle on a "hot list" of objects that may need to be garbage /// collected. /// internal static IntPtr Add(IntPtr handle, int type) { handleTypes[type - 1].Add(handle); return handle; } ////// /// Suspends GC.Collect /// [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] internal static void SuspendCollect() { lock(internalSyncObject) { suspendCount++; } } ////// /// Resumes GC.Collect /// [SuppressMessage("Microsoft.Reliability", "CA2001:AvoidCallingProblematicMethods")] [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] internal static void ResumeCollect() { bool performCollect = false; lock(internalSyncObject) { if(suspendCount > 0){ suspendCount--; } if(suspendCount == 0) { for(int i=0; i < handleTypeCount; i++) { lock(handleTypes[i]) { if (handleTypes[i].NeedCollection()) { performCollect = true; } } } } } if(performCollect) { GC.Collect(); } } ////// /// Registers a new type of handle with the handle collector. /// internal static int RegisterType(string typeName, int expense, int initialThreshold) { lock (internalSyncObject){ if (handleTypeCount == 0 || handleTypeCount == handleTypes.Length) { HandleType[] newTypes = new HandleType[handleTypeCount + 10]; if (handleTypes != null) { Array.Copy(handleTypes, 0, newTypes, 0, handleTypeCount); } handleTypes = newTypes; } handleTypes[handleTypeCount++] = new HandleType(typeName, expense, initialThreshold); return handleTypeCount; } } ////// /// Removes the given handle from the handle collector. Removing a /// handle removes it from our "hot list" of objects that should be /// frequently garbage collected. /// internal static IntPtr Remove(IntPtr handle, int type) { return handleTypes[type - 1].Remove(handle); } ////// /// Represents a specific type of handle. /// private class HandleType { internal readonly string name; private int initialThreshHold; private int threshHold; private int handleCount; private readonly int deltaPercent; #if DEBUG_HANDLECOLLECTOR private Listhandles = new List (); #endif /// /// /// Creates a new handle type. /// internal HandleType(string name, int expense, int initialThreshHold) { this.name = name; this.initialThreshHold = initialThreshHold; this.threshHold = initialThreshHold; this.deltaPercent = 100 - expense; } ////// /// Adds a handle to this handle type for monitoring. /// [SuppressMessage("Microsoft.Reliability", "CA2001:AvoidCallingProblematicMethods")] internal void Add(IntPtr handle) { if( handle == IntPtr.Zero ) { return; } bool performCollect = false; int currentCount = 0; lock(this) { handleCount++; #if DEBUG_HANDLECOLLECTOR Debug.Assert(!handles.Contains(handle)); handles.Add(handle); #endif performCollect = NeedCollection(); currentCount = handleCount; } lock (internalSyncObject){ if (HandleCollector.HandleAdded != null) { HandleCollector.HandleAdded(name, handle, currentCount); } } if (!performCollect) { return; } if (performCollect) { #if DEBUG_HANDLECOLLECTOR Debug.WriteLine("HC> Forcing garbage collect"); Debug.WriteLine("HC> name :" + name); Debug.WriteLine("HC> threshHold :" + (threshHold).ToString()); Debug.WriteLine("HC> handleCount :" + (handleCount).ToString()); Debug.WriteLine("HC> deltaPercent:" + (deltaPercent).ToString()); #endif GC.Collect(); // We just performed a GC. If the main thread is in a tight // loop there is a this will cause us to increase handles forever and prevent handle collector // from doing its job. Yield the thread here. This won't totally cause // a finalization pass but it will effectively elevate the priority // of the finalizer thread just for an instant. But how long should // we sleep? We base it on how expensive the handles are because the // more expensive the handle, the more critical that it be reclaimed. int sleep = (100 - deltaPercent) / 4; System.Threading.Thread.Sleep(sleep); } } ////// /// Retrieves the outstanding handle count for this /// handle type. /// [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] internal int GetHandleCount() { lock(this) { return handleCount; } } ////// /// Determines if this handle type needs a garbage collection pass. /// internal bool NeedCollection() { if (suspendCount > 0){ return false; } if (handleCount > threshHold) { threshHold = handleCount + ((handleCount * deltaPercent) / 100); #if DEBUG_HANDLECOLLECTOR Debug.WriteLine("HC> NeedCollection: increase threshHold to " + threshHold); #endif return true; } // If handle count < threshHold, we don't // need to collect, but if it 10% below the next lowest threshhold we // will bump down a rung. We need to choose a percentage here or else // we will oscillate. // int oldThreshHold = (100 * threshHold) / (100 + deltaPercent); if (oldThreshHold >= initialThreshHold && handleCount < (int)(oldThreshHold * .9F)) { #if DEBUG_HANDLECOLLECTOR Debug.WriteLine("HC> NeedCollection: throttle threshhold " + threshHold + " down to " + oldThreshHold); #endif threshHold = oldThreshHold; } return false; } ////// /// Removes the given handle from our monitor list. /// internal IntPtr Remove(IntPtr handle) { if( handle == IntPtr.Zero ) { return handle; } int currentCount = 0; lock(this) { handleCount--; #if DEBUG_HANDLECOLLECTOR Debug.Assert(handles.Contains(handle)); handles.Remove(handle); #endif if (handleCount < 0) { System.Diagnostics.Debug.Fail("Handle collector underflow for type '" + name + "'"); handleCount = 0; } currentCount = handleCount; } lock (internalSyncObject){ if (HandleCollector.HandleRemoved != null) { HandleCollector.HandleRemoved(name, handle, currentCount); } } return handle; } } } internal delegate void HandleChangeEventHandler(string handleType, IntPtr handleValue, int currentHandleCount); } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. // Copyright (c) Microsoft Corporation. All rights reserved. #if DEBUG_HANDLECOLLECTOR using System.Diagnostics; #endif using System.Collections.Generic; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; [module: SuppressMessage("Microsoft.Design", "CA1020:AvoidNamespacesWithFewTypes", Scope="namespace", Target="System.Internal")] namespace System.Internal { internal sealed class HandleCollector { private static HandleType[] handleTypes; private static int handleTypeCount; private static int suspendCount; internal static event HandleChangeEventHandler HandleAdded; internal static event HandleChangeEventHandler HandleRemoved; private static object internalSyncObject = new object(); ////// /// Adds the given handle to the handle collector. This keeps the /// handle on a "hot list" of objects that may need to be garbage /// collected. /// internal static IntPtr Add(IntPtr handle, int type) { handleTypes[type - 1].Add(handle); return handle; } ////// /// Suspends GC.Collect /// [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] internal static void SuspendCollect() { lock(internalSyncObject) { suspendCount++; } } ////// /// Resumes GC.Collect /// [SuppressMessage("Microsoft.Reliability", "CA2001:AvoidCallingProblematicMethods")] [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] internal static void ResumeCollect() { bool performCollect = false; lock(internalSyncObject) { if(suspendCount > 0){ suspendCount--; } if(suspendCount == 0) { for(int i=0; i < handleTypeCount; i++) { lock(handleTypes[i]) { if (handleTypes[i].NeedCollection()) { performCollect = true; } } } } } if(performCollect) { GC.Collect(); } } ////// /// Registers a new type of handle with the handle collector. /// internal static int RegisterType(string typeName, int expense, int initialThreshold) { lock (internalSyncObject){ if (handleTypeCount == 0 || handleTypeCount == handleTypes.Length) { HandleType[] newTypes = new HandleType[handleTypeCount + 10]; if (handleTypes != null) { Array.Copy(handleTypes, 0, newTypes, 0, handleTypeCount); } handleTypes = newTypes; } handleTypes[handleTypeCount++] = new HandleType(typeName, expense, initialThreshold); return handleTypeCount; } } ////// /// Removes the given handle from the handle collector. Removing a /// handle removes it from our "hot list" of objects that should be /// frequently garbage collected. /// internal static IntPtr Remove(IntPtr handle, int type) { return handleTypes[type - 1].Remove(handle); } ////// /// Represents a specific type of handle. /// private class HandleType { internal readonly string name; private int initialThreshHold; private int threshHold; private int handleCount; private readonly int deltaPercent; #if DEBUG_HANDLECOLLECTOR private Listhandles = new List (); #endif /// /// /// Creates a new handle type. /// internal HandleType(string name, int expense, int initialThreshHold) { this.name = name; this.initialThreshHold = initialThreshHold; this.threshHold = initialThreshHold; this.deltaPercent = 100 - expense; } ////// /// Adds a handle to this handle type for monitoring. /// [SuppressMessage("Microsoft.Reliability", "CA2001:AvoidCallingProblematicMethods")] internal void Add(IntPtr handle) { if( handle == IntPtr.Zero ) { return; } bool performCollect = false; int currentCount = 0; lock(this) { handleCount++; #if DEBUG_HANDLECOLLECTOR Debug.Assert(!handles.Contains(handle)); handles.Add(handle); #endif performCollect = NeedCollection(); currentCount = handleCount; } lock (internalSyncObject){ if (HandleCollector.HandleAdded != null) { HandleCollector.HandleAdded(name, handle, currentCount); } } if (!performCollect) { return; } if (performCollect) { #if DEBUG_HANDLECOLLECTOR Debug.WriteLine("HC> Forcing garbage collect"); Debug.WriteLine("HC> name :" + name); Debug.WriteLine("HC> threshHold :" + (threshHold).ToString()); Debug.WriteLine("HC> handleCount :" + (handleCount).ToString()); Debug.WriteLine("HC> deltaPercent:" + (deltaPercent).ToString()); #endif GC.Collect(); // We just performed a GC. If the main thread is in a tight // loop there is a this will cause us to increase handles forever and prevent handle collector // from doing its job. Yield the thread here. This won't totally cause // a finalization pass but it will effectively elevate the priority // of the finalizer thread just for an instant. But how long should // we sleep? We base it on how expensive the handles are because the // more expensive the handle, the more critical that it be reclaimed. int sleep = (100 - deltaPercent) / 4; System.Threading.Thread.Sleep(sleep); } } ////// /// Retrieves the outstanding handle count for this /// handle type. /// [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] internal int GetHandleCount() { lock(this) { return handleCount; } } ////// /// Determines if this handle type needs a garbage collection pass. /// internal bool NeedCollection() { if (suspendCount > 0){ return false; } if (handleCount > threshHold) { threshHold = handleCount + ((handleCount * deltaPercent) / 100); #if DEBUG_HANDLECOLLECTOR Debug.WriteLine("HC> NeedCollection: increase threshHold to " + threshHold); #endif return true; } // If handle count < threshHold, we don't // need to collect, but if it 10% below the next lowest threshhold we // will bump down a rung. We need to choose a percentage here or else // we will oscillate. // int oldThreshHold = (100 * threshHold) / (100 + deltaPercent); if (oldThreshHold >= initialThreshHold && handleCount < (int)(oldThreshHold * .9F)) { #if DEBUG_HANDLECOLLECTOR Debug.WriteLine("HC> NeedCollection: throttle threshhold " + threshHold + " down to " + oldThreshHold); #endif threshHold = oldThreshHold; } return false; } ////// /// Removes the given handle from our monitor list. /// internal IntPtr Remove(IntPtr handle) { if( handle == IntPtr.Zero ) { return handle; } int currentCount = 0; lock(this) { handleCount--; #if DEBUG_HANDLECOLLECTOR Debug.Assert(handles.Contains(handle)); handles.Remove(handle); #endif if (handleCount < 0) { System.Diagnostics.Debug.Fail("Handle collector underflow for type '" + name + "'"); handleCount = 0; } currentCount = handleCount; } lock (internalSyncObject){ if (HandleCollector.HandleRemoved != null) { HandleCollector.HandleRemoved(name, handle, currentCount); } } return handle; } } } internal delegate void HandleChangeEventHandler(string handleType, IntPtr handleValue, int currentHandleCount); } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. // Copyright (c) Microsoft Corporation. All rights reserved.
Link Menu
This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- ObjectStateEntryOriginalDbUpdatableDataRecord.cs
- RenamedEventArgs.cs
- StrokeNodeOperations.cs
- CompiledQueryCacheEntry.cs
- ExpressionPrefixAttribute.cs
- Padding.cs
- TreeSet.cs
- ErrorRuntimeConfig.cs
- Currency.cs
- ReversePositionQuery.cs
- initElementDictionary.cs
- NumericUpDown.cs
- GACIdentityPermission.cs
- HwndTarget.cs
- ContentElementCollection.cs
- SerializationFieldInfo.cs
- BindingListCollectionView.cs
- ColorConvertedBitmap.cs
- Propagator.ExtentPlaceholderCreator.cs
- UrlAuthorizationModule.cs
- MSAANativeProvider.cs
- DataGridViewLinkCell.cs
- CommandLibraryHelper.cs
- SessionStateContainer.cs
- AppDomainInfo.cs
- PrintPreviewDialog.cs
- StringDictionary.cs
- ClientConfigurationHost.cs
- ProviderConnectionPointCollection.cs
- MulticastIPAddressInformationCollection.cs
- DoubleAverageAggregationOperator.cs
- cryptoapiTransform.cs
- ParserOptions.cs
- CollectionViewGroup.cs
- ListenerTraceUtility.cs
- SliderAutomationPeer.cs
- OdbcConnectionFactory.cs
- FilteredDataSetHelper.cs
- BaseTransportHeaders.cs
- BitArray.cs
- XmlWriterSettings.cs
- RepeaterItemEventArgs.cs
- TableCellCollection.cs
- ConfigXmlElement.cs
- HttpResponse.cs
- InlineObject.cs
- TileBrush.cs
- NetPeerTcpBindingCollectionElement.cs
- VirtualPathUtility.cs
- DatatypeImplementation.cs
- ImmutableObjectAttribute.cs
- TreeViewItemAutomationPeer.cs
- RadialGradientBrush.cs
- QilXmlWriter.cs
- MenuBase.cs
- DetailsViewCommandEventArgs.cs
- Vector3D.cs
- TcpTransportManager.cs
- BitHelper.cs
- DataContractAttribute.cs
- isolationinterop.cs
- Control.cs
- StdValidatorsAndConverters.cs
- OleDbConnectionPoolGroupProviderInfo.cs
- Point4D.cs
- UriParserTemplates.cs
- Main.cs
- SizeFConverter.cs
- FrugalMap.cs
- StringPropertyBuilder.cs
- _ProxyChain.cs
- DragDeltaEventArgs.cs
- ControlsConfig.cs
- LayoutTable.cs
- ErrorEventArgs.cs
- ImpersonationContext.cs
- TreeView.cs
- FixUpCollection.cs
- NavigationPropertyEmitter.cs
- CompositeTypefaceMetrics.cs
- WebAdminConfigurationHelper.cs
- SafeViewOfFileHandle.cs
- XmlWriterTraceListener.cs
- AcceleratedTokenAuthenticator.cs
- TCPListener.cs
- AuthenticatedStream.cs
- StringValidatorAttribute.cs
- ScrollPattern.cs
- CompositeScriptReferenceEventArgs.cs
- EntityContainer.cs
- MetadataPropertyAttribute.cs
- CSharpCodeProvider.cs
- DPTypeDescriptorContext.cs
- MulticastDelegate.cs
- CodeTypeParameterCollection.cs
- PrimitiveXmlSerializers.cs
- InputLanguageProfileNotifySink.cs
- DesignerTextBoxAdapter.cs
- SessionStateUtil.cs
- FaultDescriptionCollection.cs