Code:
/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / fx / src / CommonUI / System / Drawing / Advanced / SystemColorTracker.cs / 1305376 / SystemColorTracker.cs
//------------------------------------------------------------------------------
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//-----------------------------------------------------------------------------
namespace System.Drawing.Internal {
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System;
using System.Drawing;
using Microsoft.Win32;
using System.Runtime.InteropServices;
using System.ComponentModel;
// Keeps track of objects that need to be notified of system color change events.
// Mostly this means maintaining a list of weak references.
internal class SystemColorTracker {
// when I tried the self host, it went over 500 but never over 1000.
private static int INITIAL_SIZE = 200;
// If it gets this big, I seriously miscalculated the performance of this object.
private static int WARNING_SIZE = 100000;
private static float EXPAND_THRESHOLD = 0.75f;
private static int EXPAND_FACTOR = 2;
private static WeakReference[] list = new WeakReference[INITIAL_SIZE];
private static int count = 0;
private static bool addedTracker;
// There's no such thing as a delegate to a static method,
// so we need to create an instance of something.
private SystemColorTracker() {
}
[SuppressMessage("Microsoft.Reliability", "CA2002:DoNotLockOnObjectsWithWeakIdentity")]
internal static void Add(ISystemColorTracker obj) {
lock (typeof(SystemColorTracker)) {
Debug.Assert(list != null, "List is null");
Debug.Assert(list.Length > 0, "INITIAL_SIZE was initialized after list");
if (list.Length == count) {
GarbageCollectList();
}
if (!addedTracker) {
addedTracker = true;
SystemEvents.UserPreferenceChanged += new UserPreferenceChangedEventHandler(OnUserPreferenceChanged);
}
// Strictly speaking, we should grab a lock on this class. But since the chances
// of a problem are so low, the consequences so minimal (something will get accidentally dropped
// from the list), and the performance of locking so lousy, we'll risk it.
int index = count;
count++;
// COM+ takes forever to Finalize() weak references, so it pays to reuse them.
if (list[index] == null)
list[index] = new WeakReference(obj);
else {
Debug.Assert(list[index].Target == null, "Trying to reuse a weak reference that isn't broken yet: list[" + index + "], length =" + list.Length);
list[index].Target = obj;
}
}
}
private static void CleanOutBrokenLinks() {
// Partition the list -- valid references in the low indices, broken references in the high indices.
// This is taken straight out of Sedgewick (p. 118 on quicksort).
// Basic idea is to find a broken reference on the left side of the list, and swap it with
// a valid reference on the right
int right = list.Length - 1;
int left = 0;
int length = list.Length;
// Loop invariant: everything to the left of "left" is a valid reference,
// and anything to the right of "right" is broken.
for (;;) {
while (left < length && list[left].Target != null)
left++;
while (right >= 0 && list[right].Target == null)
right--;
if (left >= right) {
count = left;
break;
}
WeakReference temp = list[left];
list[left] = list[right];
list[right] = temp;
left++;
right--;
}
Debug.Assert(count >= 0 && count <= list.Length, "count not a legal index into list");
#if DEBUG
// Check loop invariant.
// We'd like to assert that any index < count contains a valid pointer,
// but since garbage collection can happen at any time, it may have been broken
// after we partitioned it.
//
// for (int i = 0; i < count; i++) {
// Debug.Assert(list[i].Target != null, "Null found on the left side of the list");
// }
for (int i = count; i < list.Length; i++) {
Debug.Assert(list[i].Target == null, "Partitioning didn't work");
}
#endif
}
private static void GarbageCollectList() {
CleanOutBrokenLinks();
if (count / (float) list.Length > EXPAND_THRESHOLD) {
WeakReference[] newList = new WeakReference[list.Length * EXPAND_FACTOR];
list.CopyTo(newList, 0);
list = newList;
if (list.Length >= WARNING_SIZE) {
Debug.Fail("SystemColorTracker is using way more memory than expected.");
}
}
}
private static void OnUserPreferenceChanged(object sender, UserPreferenceChangedEventArgs e) {
// Update pens and brushes
if (e.Category == UserPreferenceCategory.Color) {
for (int i = 0; i < count; i++) {
Debug.Assert(list[i] != null, "null value in active part of list");
ISystemColorTracker tracker = (ISystemColorTracker) list[i].Target;
if (tracker != null) {
// If object still around
tracker.OnSystemColorChanged();
}
}
}
}
}
}
// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
//------------------------------------------------------------------------------
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//-----------------------------------------------------------------------------
namespace System.Drawing.Internal {
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System;
using System.Drawing;
using Microsoft.Win32;
using System.Runtime.InteropServices;
using System.ComponentModel;
// Keeps track of objects that need to be notified of system color change events.
// Mostly this means maintaining a list of weak references.
internal class SystemColorTracker {
// when I tried the self host, it went over 500 but never over 1000.
private static int INITIAL_SIZE = 200;
// If it gets this big, I seriously miscalculated the performance of this object.
private static int WARNING_SIZE = 100000;
private static float EXPAND_THRESHOLD = 0.75f;
private static int EXPAND_FACTOR = 2;
private static WeakReference[] list = new WeakReference[INITIAL_SIZE];
private static int count = 0;
private static bool addedTracker;
// There's no such thing as a delegate to a static method,
// so we need to create an instance of something.
private SystemColorTracker() {
}
[SuppressMessage("Microsoft.Reliability", "CA2002:DoNotLockOnObjectsWithWeakIdentity")]
internal static void Add(ISystemColorTracker obj) {
lock (typeof(SystemColorTracker)) {
Debug.Assert(list != null, "List is null");
Debug.Assert(list.Length > 0, "INITIAL_SIZE was initialized after list");
if (list.Length == count) {
GarbageCollectList();
}
if (!addedTracker) {
addedTracker = true;
SystemEvents.UserPreferenceChanged += new UserPreferenceChangedEventHandler(OnUserPreferenceChanged);
}
// Strictly speaking, we should grab a lock on this class. But since the chances
// of a problem are so low, the consequences so minimal (something will get accidentally dropped
// from the list), and the performance of locking so lousy, we'll risk it.
int index = count;
count++;
// COM+ takes forever to Finalize() weak references, so it pays to reuse them.
if (list[index] == null)
list[index] = new WeakReference(obj);
else {
Debug.Assert(list[index].Target == null, "Trying to reuse a weak reference that isn't broken yet: list[" + index + "], length =" + list.Length);
list[index].Target = obj;
}
}
}
private static void CleanOutBrokenLinks() {
// Partition the list -- valid references in the low indices, broken references in the high indices.
// This is taken straight out of Sedgewick (p. 118 on quicksort).
// Basic idea is to find a broken reference on the left side of the list, and swap it with
// a valid reference on the right
int right = list.Length - 1;
int left = 0;
int length = list.Length;
// Loop invariant: everything to the left of "left" is a valid reference,
// and anything to the right of "right" is broken.
for (;;) {
while (left < length && list[left].Target != null)
left++;
while (right >= 0 && list[right].Target == null)
right--;
if (left >= right) {
count = left;
break;
}
WeakReference temp = list[left];
list[left] = list[right];
list[right] = temp;
left++;
right--;
}
Debug.Assert(count >= 0 && count <= list.Length, "count not a legal index into list");
#if DEBUG
// Check loop invariant.
// We'd like to assert that any index < count contains a valid pointer,
// but since garbage collection can happen at any time, it may have been broken
// after we partitioned it.
//
// for (int i = 0; i < count; i++) {
// Debug.Assert(list[i].Target != null, "Null found on the left side of the list");
// }
for (int i = count; i < list.Length; i++) {
Debug.Assert(list[i].Target == null, "Partitioning didn't work");
}
#endif
}
private static void GarbageCollectList() {
CleanOutBrokenLinks();
if (count / (float) list.Length > EXPAND_THRESHOLD) {
WeakReference[] newList = new WeakReference[list.Length * EXPAND_FACTOR];
list.CopyTo(newList, 0);
list = newList;
if (list.Length >= WARNING_SIZE) {
Debug.Fail("SystemColorTracker is using way more memory than expected.");
}
}
}
private static void OnUserPreferenceChanged(object sender, UserPreferenceChangedEventArgs e) {
// Update pens and brushes
if (e.Category == UserPreferenceCategory.Color) {
for (int i = 0; i < count; i++) {
Debug.Assert(list[i] != null, "null value in active part of list");
ISystemColorTracker tracker = (ISystemColorTracker) list[i].Target;
if (tracker != null) {
// If object still around
tracker.OnSystemColorChanged();
}
}
}
}
}
}
// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
Link Menu

This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- DbInsertCommandTree.cs
- SessionEndingEventArgs.cs
- DecoderReplacementFallback.cs
- PolicyManager.cs
- NameObjectCollectionBase.cs
- DesigntimeLicenseContext.cs
- PrintSchema.cs
- OrderedParallelQuery.cs
- OleServicesContext.cs
- SqlGatherProducedAliases.cs
- BinaryConverter.cs
- AlphabeticalEnumConverter.cs
- SectionInformation.cs
- FilterQueryOptionExpression.cs
- ObjectTokenCategory.cs
- AudioException.cs
- FixedHyperLink.cs
- UIElementIsland.cs
- FacetDescriptionElement.cs
- SolidColorBrush.cs
- JumpPath.cs
- ConfigViewGenerator.cs
- XslAstAnalyzer.cs
- Vector3DConverter.cs
- HtmlInputReset.cs
- SelectionPattern.cs
- MultiDataTrigger.cs
- SafeTokenHandle.cs
- TemplateLookupAction.cs
- TextWriter.cs
- XmlSchemaAttributeGroup.cs
- FileDialog.cs
- DataGridViewSortCompareEventArgs.cs
- X509IssuerSerialKeyIdentifierClause.cs
- CapabilitiesPattern.cs
- ExtenderProvidedPropertyAttribute.cs
- CompensationToken.cs
- ColumnReorderedEventArgs.cs
- UnsafeCollabNativeMethods.cs
- XmlNamespaceDeclarationsAttribute.cs
- ZoomPercentageConverter.cs
- InspectionWorker.cs
- AstNode.cs
- ListViewTableRow.cs
- TableLayoutPanelCellPosition.cs
- NameValueConfigurationElement.cs
- DefaultBinder.cs
- DictionaryContent.cs
- EnumerableCollectionView.cs
- XamlTreeBuilder.cs
- ErrorTableItemStyle.cs
- GenericEnumerator.cs
- TextSpanModifier.cs
- TemplateColumn.cs
- ImageList.cs
- WebPartCatalogCloseVerb.cs
- ControlOperationInvoker.cs
- PropertyEntry.cs
- DataGridViewRowErrorTextNeededEventArgs.cs
- RegexParser.cs
- ElementProxy.cs
- DispatcherProcessingDisabled.cs
- MarshalDirectiveException.cs
- FrameAutomationPeer.cs
- OSFeature.cs
- ActivityExecutorDelegateInfo.cs
- DataErrorValidationRule.cs
- DocumentEventArgs.cs
- DbProviderFactoriesConfigurationHandler.cs
- ListItem.cs
- InkCanvasAutomationPeer.cs
- DateTimeConverter2.cs
- CodeGroup.cs
- CLRBindingWorker.cs
- SafeFileMapViewHandle.cs
- ManagementOptions.cs
- ListControlStringCollectionEditor.cs
- DesignerActionTextItem.cs
- ManagementPath.cs
- BaseConfigurationRecord.cs
- TypeConverterAttribute.cs
- SspiSafeHandles.cs
- Soap12ServerProtocol.cs
- DataBindingList.cs
- Utils.cs
- DesignerDataTable.cs
- HttpCacheVaryByContentEncodings.cs
- SplitterCancelEvent.cs
- AspNetCacheProfileAttribute.cs
- SessionStateSection.cs
- ColumnPropertiesGroup.cs
- PersianCalendar.cs
- RuntimeIdentifierPropertyAttribute.cs
- MasterPageBuildProvider.cs
- ExpressionNode.cs
- WindowsScrollBarBits.cs
- TableLayout.cs
- AnnotationService.cs
- ComPlusDiagnosticTraceRecords.cs
- ExitEventArgs.cs