Code:
/ Net / Net / 3.5.50727.3053 / DEVDIV / depot / DevDiv / releases / Orcas / SP / wpf / src / Shared / MS / Internal / SizeLimitedCache.cs / 1 / 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
- LayoutTableCell.cs
- _ListenerResponseStream.cs
- TextDecoration.cs
- GradientSpreadMethodValidation.cs
- ScrollChrome.cs
- StatusBarDrawItemEvent.cs
- XmlAttributeAttribute.cs
- EmptyControlCollection.cs
- StorageMappingItemLoader.cs
- DBSqlParserTableCollection.cs
- CryptoHandle.cs
- PnrpPeerResolver.cs
- CookieHandler.cs
- SoapSchemaMember.cs
- MemberHolder.cs
- DataObject.cs
- CellTreeNodeVisitors.cs
- XPathItem.cs
- PrivilegeNotHeldException.cs
- QilCloneVisitor.cs
- Transform3DCollection.cs
- KeyInterop.cs
- Rfc2898DeriveBytes.cs
- cache.cs
- CodeGotoStatement.cs
- CodeDomSerializerException.cs
- ErrorView.xaml.cs
- GestureRecognitionResult.cs
- PerformanceCounterLib.cs
- WmpBitmapDecoder.cs
- BackgroundWorker.cs
- ButtonBase.cs
- DiscoveryClientProtocol.cs
- FusionWrap.cs
- RolePrincipal.cs
- ProxyWebPartManager.cs
- EntitySqlException.cs
- WebBaseEventKeyComparer.cs
- XmlNamespaceMappingCollection.cs
- ParameterElementCollection.cs
- XmlSchemaSimpleTypeList.cs
- CallId.cs
- JsonSerializer.cs
- IPAddress.cs
- UInt32Converter.cs
- DataObjectFieldAttribute.cs
- ProcessManager.cs
- Debugger.cs
- DataGridAutoFormatDialog.cs
- InternalRelationshipCollection.cs
- AbsoluteQuery.cs
- CompoundFileStorageReference.cs
- Intellisense.cs
- SignerInfo.cs
- ShaperBuffers.cs
- FontSource.cs
- BufferedWebEventProvider.cs
- JsonQNameDataContract.cs
- SessionEndedEventArgs.cs
- WCFServiceClientProxyGenerator.cs
- EntityContainerRelationshipSet.cs
- DropSourceBehavior.cs
- IndexerNameAttribute.cs
- ObjectViewFactory.cs
- WbemProvider.cs
- RangeBaseAutomationPeer.cs
- SmtpLoginAuthenticationModule.cs
- TdsParameterSetter.cs
- PageAsyncTaskManager.cs
- DataGridHyperlinkColumn.cs
- ToolStripPanel.cs
- WrapperEqualityComparer.cs
- CalendarSelectionChangedEventArgs.cs
- StylusButtonCollection.cs
- X509CertificateValidator.cs
- HandlerFactoryCache.cs
- SerializationFieldInfo.cs
- CounterCreationData.cs
- OSEnvironmentHelper.cs
- WebPartCatalogAddVerb.cs
- _NegotiateClient.cs
- AngleUtil.cs
- AppDomain.cs
- CodeAssignStatement.cs
- GeneratedCodeAttribute.cs
- DocumentOrderQuery.cs
- CompilationSection.cs
- ActivityCollectionMarkupSerializer.cs
- DataRelation.cs
- TextProviderWrapper.cs
- XmlReaderSettings.cs
- CodeDomLoader.cs
- TraceSection.cs
- ImageList.cs
- ListDictionary.cs
- FontWeightConverter.cs
- ComEventsInfo.cs
- GetKeyedHashRequest.cs
- MetafileEditor.cs
- GetWorkflowTree.cs