Code:
/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / wpf / src / Shared / MS / Internal / SizeLimitedCache.cs / 1305600 / SizeLimitedCache.cs
using System; using System.Collections.Generic; using MS.Internal.PresentationCore; namespace MS.Internal { ////// Implementation of a cache with a limited size (a limited number of items /// can be stored in the cache). When adding to a full cache, the element /// that was last accessed is removed. Also, the cache supports permanent items /// which are not subject to removal or change. /// ////// The cache is stored in a hash table. The hash table maps /// keys to nodes in a linked list. Each node contains the required /// info (key, resource, permanence flag). The linked list is what /// maintains the order in which items should be removed. The beginning /// (_begin.Next) is the first to be removed and the end (_end.Previous) /// is the last to be removed. Every time a node is accessed or /// changed, it gets moved to the end of the list. Also, permanent items, /// though in the hash table, are NOT in the linked list. /// [FriendAccessAllowed] internal class SizeLimitedCache{ //****************************************************** // Constructors // *************************************************** /// /// Constructs a ResourceCache instance /// /// /// The maximum number of nonpermanent resources the cache can store. /// public SizeLimitedCache(int maximumItems) { if (maximumItems <= 0) { throw new ArgumentOutOfRangeException("maximumItems"); } _maximumItems = maximumItems; _permanentCount = 0; // set up an empty list. // the _begin and _end nodes are empty nodes marking the begin and // end of the list. _begin = new Node(default(K), default(V), false); _end = new Node(default(K), default(V), false); _begin.Next = _end; _end.Previous = _begin; _nodeLookup = new Dictionary(); } //***************************************************** // Public Properties // *************************************************** /// /// Returns the maximum number of nonpermanent resources the cache can store. /// public int MaximumItems { get { return _maximumItems; } } //****************************************************** // Public Methods // *************************************************** ////// Add an item to the cache. If the cache is full, the last item /// to have been accessed is removed. Permanent objects are not /// included in the count to determine if the cache is full. /// /// /// The key of the object to add. /// /// /// The object to be stored in the cache. /// /// /// bool indicating if the object to be cached will always be left /// in the cache upon adding to a full cache. /// public void Add(K key, V resource, bool isPermanent) { if ( (object)key == null) { throw new ArgumentNullException("key"); } if ( (object)resource == null) { throw new ArgumentNullException("resource"); } // note: [] throws, thus we should check if its in the dictionary first. if (!_nodeLookup.ContainsKey(key)) { Node node = new Node(key, resource, isPermanent); if (!isPermanent) { if (IsFull()) { RemoveOldest(); } InsertAtEnd(node); } else { _permanentCount++; } _nodeLookup[key] = node; } else { Node node = _nodeLookup[key]; if (!node.IsPermanent) { RemoveFromList(node); } if (!node.IsPermanent && isPermanent) { _permanentCount++; } else if (node.IsPermanent && !isPermanent) { _permanentCount--; if (IsFull()) { RemoveOldest(); } } node.IsPermanent = isPermanent; node.Resource = resource; if (!isPermanent) { InsertAtEnd(node); } } } ////// Remove an item from the cache. /// /// /// The key of the object to remove. /// public void Remove(K key) { if ( (object)key == null) { throw new ArgumentNullException("key"); } // note: [] throws, thus we should check if its in the dictionary first. if (!_nodeLookup.ContainsKey(key)) { return; } Node node = _nodeLookup[key]; _nodeLookup.Remove(key); if (!node.IsPermanent) { RemoveFromList(node); } else { _permanentCount--; } } ////// Retrieve an item from the cache. /// /// /// The key of the object to get. /// ////// The object stored in the cache based on the key. If the key is not /// contained in the class, V.default is returned (Use the Contains method /// if V is a value type) /// public V Get(K key) { if ( (object)key == null) { throw new ArgumentNullException("key"); } // note: [] throws, thus we should check if its in the dictionary first. if (!_nodeLookup.ContainsKey(key)) { return default(V); } Node node = _nodeLookup[key]; if (!node.IsPermanent) { RemoveFromList(node); InsertAtEnd(node); } return node.Resource; } //****************************************************** // Private Methods // **************************************************** ////// Remove the oldest nonpermanent item in the cache. /// private void RemoveOldest() { Node node = _begin.Next; _nodeLookup.Remove(node.Key); RemoveFromList(node); } ////// Inserts a node at the end of the linked list /// /// /// The node to insert /// private void InsertAtEnd(Node node) { node.Next = _end; node.Previous = _end.Previous; node.Previous.Next = node; _end.Previous = node; } ////// Removes an item from the linked list /// /// /// The node to remove /// private void RemoveFromList(Node node) { node.Previous.Next = node.Next; node.Next.Previous = node.Previous; } ////// Check if the cache is full. Do not include permanent items /// in the count. /// ////// true if the cache is full. false if not. /// private bool IsFull() { return (_nodeLookup.Count - _permanentCount >= _maximumItems); } ////// Doubly linked list node class. Has 3 values: key, resource, permanence flag /// private class Node { public Node(K key, V resource, bool isPermanent) { Key = key; Resource = resource; IsPermanent = isPermanent; } public K Key { get { return _key; } set { _key = value; } } public V Resource { get { return _resource; } set { _resource = value; } } public bool IsPermanent { get { return _isPermanent; } set { _isPermanent = value; } } public Node Next { get { return _next; } set { _next = value; } } public Node Previous { get { return _previous; } set { _previous = value; } } private V _resource; private K _key; private bool _isPermanent; private Node _next; private Node _previous; } //***************************************************** // Private Fields // **************************************************** // the maximum nonpermanent items allowed private int _maximumItems; // need to keep a separate counter for permanent items private int _permanentCount; // the _begin and _end nodes are empty nodes marking the begin and // end of the list. private Node _begin; private Node _end; // the hashtable mapping keys to nodes private Dictionary_nodeLookup; } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. // Copyright (c) Microsoft Corporation. All rights reserved. using System; using System.Collections.Generic; using MS.Internal.PresentationCore; namespace MS.Internal { /// /// Implementation of a cache with a limited size (a limited number of items /// can be stored in the cache). When adding to a full cache, the element /// that was last accessed is removed. Also, the cache supports permanent items /// which are not subject to removal or change. /// ////// The cache is stored in a hash table. The hash table maps /// keys to nodes in a linked list. Each node contains the required /// info (key, resource, permanence flag). The linked list is what /// maintains the order in which items should be removed. The beginning /// (_begin.Next) is the first to be removed and the end (_end.Previous) /// is the last to be removed. Every time a node is accessed or /// changed, it gets moved to the end of the list. Also, permanent items, /// though in the hash table, are NOT in the linked list. /// [FriendAccessAllowed] internal class SizeLimitedCache{ //****************************************************** // Constructors // *************************************************** /// /// Constructs a ResourceCache instance /// /// /// The maximum number of nonpermanent resources the cache can store. /// public SizeLimitedCache(int maximumItems) { if (maximumItems <= 0) { throw new ArgumentOutOfRangeException("maximumItems"); } _maximumItems = maximumItems; _permanentCount = 0; // set up an empty list. // the _begin and _end nodes are empty nodes marking the begin and // end of the list. _begin = new Node(default(K), default(V), false); _end = new Node(default(K), default(V), false); _begin.Next = _end; _end.Previous = _begin; _nodeLookup = new Dictionary(); } //***************************************************** // Public Properties // *************************************************** /// /// Returns the maximum number of nonpermanent resources the cache can store. /// public int MaximumItems { get { return _maximumItems; } } //****************************************************** // Public Methods // *************************************************** ////// Add an item to the cache. If the cache is full, the last item /// to have been accessed is removed. Permanent objects are not /// included in the count to determine if the cache is full. /// /// /// The key of the object to add. /// /// /// The object to be stored in the cache. /// /// /// bool indicating if the object to be cached will always be left /// in the cache upon adding to a full cache. /// public void Add(K key, V resource, bool isPermanent) { if ( (object)key == null) { throw new ArgumentNullException("key"); } if ( (object)resource == null) { throw new ArgumentNullException("resource"); } // note: [] throws, thus we should check if its in the dictionary first. if (!_nodeLookup.ContainsKey(key)) { Node node = new Node(key, resource, isPermanent); if (!isPermanent) { if (IsFull()) { RemoveOldest(); } InsertAtEnd(node); } else { _permanentCount++; } _nodeLookup[key] = node; } else { Node node = _nodeLookup[key]; if (!node.IsPermanent) { RemoveFromList(node); } if (!node.IsPermanent && isPermanent) { _permanentCount++; } else if (node.IsPermanent && !isPermanent) { _permanentCount--; if (IsFull()) { RemoveOldest(); } } node.IsPermanent = isPermanent; node.Resource = resource; if (!isPermanent) { InsertAtEnd(node); } } } ////// Remove an item from the cache. /// /// /// The key of the object to remove. /// public void Remove(K key) { if ( (object)key == null) { throw new ArgumentNullException("key"); } // note: [] throws, thus we should check if its in the dictionary first. if (!_nodeLookup.ContainsKey(key)) { return; } Node node = _nodeLookup[key]; _nodeLookup.Remove(key); if (!node.IsPermanent) { RemoveFromList(node); } else { _permanentCount--; } } ////// Retrieve an item from the cache. /// /// /// The key of the object to get. /// ////// The object stored in the cache based on the key. If the key is not /// contained in the class, V.default is returned (Use the Contains method /// if V is a value type) /// public V Get(K key) { if ( (object)key == null) { throw new ArgumentNullException("key"); } // note: [] throws, thus we should check if its in the dictionary first. if (!_nodeLookup.ContainsKey(key)) { return default(V); } Node node = _nodeLookup[key]; if (!node.IsPermanent) { RemoveFromList(node); InsertAtEnd(node); } return node.Resource; } //****************************************************** // Private Methods // **************************************************** ////// Remove the oldest nonpermanent item in the cache. /// private void RemoveOldest() { Node node = _begin.Next; _nodeLookup.Remove(node.Key); RemoveFromList(node); } ////// Inserts a node at the end of the linked list /// /// /// The node to insert /// private void InsertAtEnd(Node node) { node.Next = _end; node.Previous = _end.Previous; node.Previous.Next = node; _end.Previous = node; } ////// Removes an item from the linked list /// /// /// The node to remove /// private void RemoveFromList(Node node) { node.Previous.Next = node.Next; node.Next.Previous = node.Previous; } ////// Check if the cache is full. Do not include permanent items /// in the count. /// ////// true if the cache is full. false if not. /// private bool IsFull() { return (_nodeLookup.Count - _permanentCount >= _maximumItems); } ////// Doubly linked list node class. Has 3 values: key, resource, permanence flag /// private class Node { public Node(K key, V resource, bool isPermanent) { Key = key; Resource = resource; IsPermanent = isPermanent; } public K Key { get { return _key; } set { _key = value; } } public V Resource { get { return _resource; } set { _resource = value; } } public bool IsPermanent { get { return _isPermanent; } set { _isPermanent = value; } } public Node Next { get { return _next; } set { _next = value; } } public Node Previous { get { return _previous; } set { _previous = value; } } private V _resource; private K _key; private bool _isPermanent; private Node _next; private Node _previous; } //***************************************************** // Private Fields // **************************************************** // the maximum nonpermanent items allowed private int _maximumItems; // need to keep a separate counter for permanent items private int _permanentCount; // the _begin and _end nodes are empty nodes marking the begin and // end of the list. private Node _begin; private Node _end; // the hashtable mapping keys to nodes private Dictionary_nodeLookup; } } // 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
- OutOfProcStateClientManager.cs
- UrlPath.cs
- ValidationUtility.cs
- MarginsConverter.cs
- XsltOutput.cs
- PolygonHotSpot.cs
- SBCSCodePageEncoding.cs
- XmlSchemaSimpleContentRestriction.cs
- Int32Converter.cs
- DateTimeConverter.cs
- CqlGenerator.cs
- SmiConnection.cs
- DetailsViewRowCollection.cs
- objectresult_tresulttype.cs
- PeerNameRecord.cs
- KeyToListMap.cs
- Translator.cs
- SignatureDescription.cs
- UnsafeNetInfoNativeMethods.cs
- EnlistmentTraceIdentifier.cs
- ScriptingAuthenticationServiceSection.cs
- TraceRecords.cs
- CheckedListBox.cs
- TableLayoutRowStyleCollection.cs
- WebException.cs
- MouseGestureConverter.cs
- AccessKeyManager.cs
- ControlPropertyNameConverter.cs
- CorrelationManager.cs
- SerializationInfoEnumerator.cs
- FactoryRecord.cs
- EdmComplexTypeAttribute.cs
- ResourceProviderFactory.cs
- SymmetricKey.cs
- Utilities.cs
- MDIClient.cs
- IndexerNameAttribute.cs
- PauseStoryboard.cs
- FileSystemInfo.cs
- TextServicesCompartmentContext.cs
- util.cs
- SplayTreeNode.cs
- ConfigPathUtility.cs
- ReadOnlyObservableCollection.cs
- Matrix.cs
- InstallerTypeAttribute.cs
- OpenTypeLayoutCache.cs
- Emitter.cs
- ToolStripArrowRenderEventArgs.cs
- TableLayoutSettingsTypeConverter.cs
- Processor.cs
- SortedDictionary.cs
- XmlAnyElementAttributes.cs
- CrossAppDomainChannel.cs
- shaper.cs
- TextServicesCompartment.cs
- FixedPage.cs
- XmlCDATASection.cs
- Matrix3DValueSerializer.cs
- ToolZone.cs
- ToolStripDropDownMenu.cs
- QueryGenerator.cs
- EmptyEnumerator.cs
- OlePropertyStructs.cs
- COM2PropertyBuilderUITypeEditor.cs
- control.ime.cs
- DbCommandTree.cs
- CachedFontFamily.cs
- ConfigXmlComment.cs
- MbpInfo.cs
- URLEditor.cs
- DataTableCollection.cs
- ListItem.cs
- UrlPath.cs
- ControlIdConverter.cs
- ControlTemplate.cs
- HttpWebRequest.cs
- AttributeExtensions.cs
- DataControlPagerLinkButton.cs
- DetailsViewInsertedEventArgs.cs
- RayHitTestParameters.cs
- ResourceDescriptionAttribute.cs
- CompositeActivityMarkupSerializer.cs
- UpdatePanelTrigger.cs
- RuntimeConfigurationRecord.cs
- AuthorizationRule.cs
- TextServicesProperty.cs
- DefaultValidator.cs
- CounterCreationData.cs
- OneOfTypeConst.cs
- PreviewKeyDownEventArgs.cs
- PathFigureCollection.cs
- StandardOleMarshalObject.cs
- ListSurrogate.cs
- InheritanceContextHelper.cs
- TrailingSpaceComparer.cs
- Bidi.cs
- DatePickerTextBox.cs
- ElementFactory.cs
- UshortList2.cs