|
|
@@ -3,56 +3,51 @@
|
|
|
//
|
|
|
// Author:
|
|
|
// Patrik Torstensson ([email protected])
|
|
|
-// Changes:
|
|
|
// Daniel Cazzulino [DHC] ([email protected])
|
|
|
//
|
|
|
-// (C) Copyright Patrik Torstensson, 2001
|
|
|
-//
|
|
|
-namespace System.Web.Caching
|
|
|
-{
|
|
|
+
|
|
|
+using System;
|
|
|
+using System.Collections;
|
|
|
+using System.Threading;
|
|
|
+
|
|
|
+namespace System.Web.Caching {
|
|
|
/// <summary>
|
|
|
/// Responsible for holding a cache entry in the linked list bucket.
|
|
|
/// </summary>
|
|
|
- internal struct ExpiresEntry
|
|
|
- {
|
|
|
- internal CacheEntry _objEntry;
|
|
|
- internal long _ticksExpires;
|
|
|
+ internal struct ExpiresEntry {
|
|
|
+ internal CacheEntry Entry;
|
|
|
+ internal long TicksExpires;
|
|
|
internal int _intNext;
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
/// Holds cache entries that has a expiration in a bucket list.
|
|
|
/// </summary>
|
|
|
- internal class ExpiresBucket
|
|
|
- {
|
|
|
- private static int MIN_ENTRIES = 16;
|
|
|
+ internal class ExpiresBucket {
|
|
|
+ private static int MIN_ENTRIES = 4;
|
|
|
|
|
|
- private byte _byteID;
|
|
|
- private int _intSize;
|
|
|
- private int _intCount;
|
|
|
- private int _intNext;
|
|
|
+ private byte _byteID;
|
|
|
+ private int _intSize;
|
|
|
+ private int _intCount;
|
|
|
+ private int _intNext;
|
|
|
|
|
|
- private Cache _objManager;
|
|
|
+ private Cache _objManager;
|
|
|
|
|
|
private ExpiresEntry [] _arrEntries;
|
|
|
|
|
|
- /// <summary>
|
|
|
- /// A lock to use for syncronized operations. [DHC]
|
|
|
- /// </summary>
|
|
|
private System.Threading.ReaderWriterLock _lock = new System.Threading.ReaderWriterLock();
|
|
|
|
|
|
/// <summary>
|
|
|
/// Keeps a list of indexes in the list which are available to place new items. [DHC]
|
|
|
/// </summary>
|
|
|
- Int32Collection _freeidx = new Int32Collection();
|
|
|
+ private Int32Collection _freeidx = new Int32Collection();
|
|
|
|
|
|
/// <summary>
|
|
|
/// Constructs a new bucket.
|
|
|
/// </summary>
|
|
|
/// <param name="bucket">Current bucket ID.</param>
|
|
|
/// <param name="objManager">Cache manager reponsible for the item(s) in the expires bucket.</param>
|
|
|
- internal ExpiresBucket(byte bucket, Cache objManager)
|
|
|
- {
|
|
|
+ internal ExpiresBucket (byte bucket, Cache objManager) {
|
|
|
_objManager = objManager;
|
|
|
Initialize(bucket);
|
|
|
}
|
|
|
@@ -61,22 +56,18 @@ namespace System.Web.Caching
|
|
|
/// Initializes the expires bucket, creates a linked list of MIN_ENTRIES.
|
|
|
/// </summary>
|
|
|
/// <param name="bucket">Bucket ID.</param>
|
|
|
- private void Initialize(byte bucket)
|
|
|
- {
|
|
|
+ private void Initialize (byte bucket) {
|
|
|
_byteID = bucket;
|
|
|
_intNext = 0;
|
|
|
_intCount = 0;
|
|
|
|
|
|
- _arrEntries = new ExpiresEntry[MIN_ENTRIES];
|
|
|
+ _arrEntries = new ExpiresEntry [MIN_ENTRIES];
|
|
|
_intSize = MIN_ENTRIES;
|
|
|
|
|
|
int intPos = 0;
|
|
|
- do
|
|
|
- {
|
|
|
+ do {
|
|
|
_arrEntries[intPos]._intNext = intPos + 1;
|
|
|
- //HACK: [DHC] Use constant defined in Cache.
|
|
|
- //_arrEntries[intPos]._ticksExpires = System.DateTime.MaxValue.Ticks;
|
|
|
- _arrEntries[intPos]._ticksExpires = Cache.NoAbsoluteExpiration.Ticks;
|
|
|
+ _arrEntries[intPos].TicksExpires = Cache.NoAbsoluteExpiration.Ticks;
|
|
|
|
|
|
intPos++;
|
|
|
} while (intPos < _intSize);
|
|
|
@@ -87,11 +78,9 @@ namespace System.Web.Caching
|
|
|
/// <summary>
|
|
|
/// Expands the bucket linked array list.
|
|
|
/// </summary>
|
|
|
- private void Expand()
|
|
|
- {
|
|
|
+ private void Expand () {
|
|
|
_lock.AcquireWriterLock(-1);
|
|
|
- try
|
|
|
- {
|
|
|
+ try {
|
|
|
int oldsize = _intSize;
|
|
|
_intSize *= 2;
|
|
|
|
|
|
@@ -104,10 +93,9 @@ namespace System.Web.Caching
|
|
|
newlist[oldsize - 1]._intNext = oldsize;
|
|
|
|
|
|
// Initialize positions for the rest of new elements.
|
|
|
- for (int i = oldsize; i < _intSize; i++)
|
|
|
- {
|
|
|
+ for (int i = oldsize; i < _intSize; i++) {
|
|
|
newlist[i]._intNext = i + 1;
|
|
|
- newlist[i]._ticksExpires = Cache.NoAbsoluteExpiration.Ticks;
|
|
|
+ newlist[i].TicksExpires = Cache.NoAbsoluteExpiration.Ticks;
|
|
|
}
|
|
|
|
|
|
// Last item signals the expansion of the list.
|
|
|
@@ -116,8 +104,7 @@ namespace System.Web.Caching
|
|
|
// Replace the existing list.
|
|
|
_arrEntries = newlist;
|
|
|
}
|
|
|
- finally
|
|
|
- {
|
|
|
+ finally {
|
|
|
_lock.ReleaseWriterLock();
|
|
|
}
|
|
|
|
|
|
@@ -127,61 +114,34 @@ namespace System.Web.Caching
|
|
|
/// Adds a cache entry into the expires bucket.
|
|
|
/// </summary>
|
|
|
/// <param name="objEntry">Cache Entry object to be added.</param>
|
|
|
- internal void Add(CacheEntry objEntry)
|
|
|
- {
|
|
|
- bool dogrow = false;
|
|
|
-
|
|
|
- // Check the need for expansion or reuse free index.
|
|
|
- if (_intNext == -1)
|
|
|
- {
|
|
|
- if (_freeidx.Count == 0)
|
|
|
- {
|
|
|
- dogrow = true;
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- _lock.AcquireReaderLock(-1);
|
|
|
- try
|
|
|
- {
|
|
|
- // Elements may have been removed before the lock statement.
|
|
|
- if (_freeidx.Count == 0)
|
|
|
- dogrow = true;
|
|
|
- else
|
|
|
- {
|
|
|
- _intNext = _freeidx[0];
|
|
|
- _freeidx.Remove(_intNext);
|
|
|
- }
|
|
|
- }
|
|
|
- finally
|
|
|
- {
|
|
|
- _lock.ReleaseReaderLock();
|
|
|
+ internal void Add (CacheEntry objEntry) {
|
|
|
+ _lock.AcquireWriterLock(-1);
|
|
|
+ try {
|
|
|
+ if (_intNext == -1) {
|
|
|
+ if (_freeidx.Count == 0)
|
|
|
+ Expand();
|
|
|
+ else {
|
|
|
+ _intNext = _freeidx[0];
|
|
|
+ _freeidx.Remove(_intNext);
|
|
|
}
|
|
|
}
|
|
|
- }
|
|
|
-
|
|
|
- if (dogrow)
|
|
|
- Expand();
|
|
|
|
|
|
- _lock.AcquireWriterLock(-1);
|
|
|
- try
|
|
|
- {
|
|
|
- _arrEntries[_intNext]._ticksExpires = objEntry.Expires;
|
|
|
- _arrEntries[_intNext]._objEntry = objEntry;
|
|
|
+ _arrEntries[_intNext].TicksExpires = objEntry.Expires;
|
|
|
+ _arrEntries[_intNext].Entry = objEntry;
|
|
|
+
|
|
|
+ objEntry.ExpiresBucket = _byteID;
|
|
|
+ objEntry.ExpiresIndex = _intNext;
|
|
|
+
|
|
|
// If there are free indexes in the list, reuse them for the _next value.
|
|
|
- if (_freeidx.Count != 0)
|
|
|
- {
|
|
|
- _intNext = _freeidx[0];
|
|
|
+ if (_freeidx.Count != 0) {
|
|
|
+ _intNext = _freeidx [0];
|
|
|
_freeidx.Remove(_intNext);
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
+ } else
|
|
|
_intNext = _arrEntries[_intNext]._intNext;
|
|
|
- }
|
|
|
|
|
|
_intCount++;
|
|
|
}
|
|
|
- finally
|
|
|
- {
|
|
|
+ finally {
|
|
|
_lock.ReleaseWriterLock();
|
|
|
}
|
|
|
}
|
|
|
@@ -190,28 +150,25 @@ namespace System.Web.Caching
|
|
|
/// Removes a cache entry from the expires bucket.
|
|
|
/// </summary>
|
|
|
/// <param name="objEntry">Cache entry to be removed.</param>
|
|
|
- internal void Remove(CacheEntry objEntry)
|
|
|
- {
|
|
|
+ internal void Remove(CacheEntry objEntry) {
|
|
|
// Check if this is our bucket
|
|
|
- if (objEntry.ExpiresIndex != _byteID) return;
|
|
|
+ if (objEntry.ExpiresBucket != _byteID) return;
|
|
|
if (objEntry.ExpiresIndex == CacheEntry.NoIndexInBucket) return;
|
|
|
|
|
|
_lock.AcquireWriterLock(-1);
|
|
|
- try
|
|
|
- {
|
|
|
+ try {
|
|
|
if (_arrEntries.Length < objEntry.ExpiresIndex) return;
|
|
|
_intCount--;
|
|
|
|
|
|
// Push the index as a free one.
|
|
|
_freeidx.Add(objEntry.ExpiresIndex);
|
|
|
|
|
|
- _arrEntries[objEntry.ExpiresIndex]._objEntry = null;
|
|
|
+ _arrEntries[objEntry.ExpiresIndex].Entry = null;
|
|
|
// Clear bucket-related values from the item.
|
|
|
objEntry.ExpiresBucket = CacheEntry.NoBucketHash;
|
|
|
objEntry.ExpiresIndex = CacheEntry.NoIndexInBucket;
|
|
|
}
|
|
|
- finally
|
|
|
- {
|
|
|
+ finally {
|
|
|
//Releases both reader & writer locks
|
|
|
_lock.ReleaseWriterLock();
|
|
|
}
|
|
|
@@ -224,23 +181,20 @@ namespace System.Web.Caching
|
|
|
/// </summary>
|
|
|
/// <param name="objEntry">Cache entry to update.</param>
|
|
|
/// <param name="ticksExpires">New expiration value for the cache entry.</param>
|
|
|
- internal void Update(CacheEntry objEntry, long ticksExpires)
|
|
|
- {
|
|
|
+ internal void Update(CacheEntry objEntry, long ticksExpires) {
|
|
|
// Check if this is our bucket
|
|
|
- if (objEntry.ExpiresIndex != _byteID) return;
|
|
|
+ if (objEntry.ExpiresBucket != _byteID) return;
|
|
|
if (objEntry.ExpiresIndex == CacheEntry.NoIndexInBucket) return;
|
|
|
|
|
|
_lock.AcquireWriterLock(-1);
|
|
|
- try
|
|
|
- {
|
|
|
+ try {
|
|
|
if (_arrEntries.Length < objEntry.ExpiresIndex) return;
|
|
|
|
|
|
// Proceed to update.
|
|
|
- _arrEntries[objEntry.ExpiresIndex]._ticksExpires = ticksExpires;
|
|
|
- _arrEntries[objEntry.ExpiresIndex]._objEntry.Expires = ticksExpires;
|
|
|
+ _arrEntries[objEntry.ExpiresIndex].TicksExpires = ticksExpires;
|
|
|
+ _arrEntries[objEntry.ExpiresIndex].Entry.Expires = ticksExpires;
|
|
|
}
|
|
|
- finally
|
|
|
- {
|
|
|
+ finally {
|
|
|
//Releases both read & write locks
|
|
|
_lock.ReleaseWriterLock();
|
|
|
}
|
|
|
@@ -249,82 +203,82 @@ namespace System.Web.Caching
|
|
|
/// <summary>
|
|
|
/// Flushes all cache entries that has expired and removes them from the cache manager.
|
|
|
/// </summary>
|
|
|
- internal void FlushExpiredItems()
|
|
|
- {
|
|
|
+ internal void FlushExpiredItems() {
|
|
|
ExpiresEntry objEntry;
|
|
|
- CacheEntry [] arrCacheEntries;
|
|
|
-
|
|
|
- int intCachePos;
|
|
|
- int intPos;
|
|
|
- long ticksNow;
|
|
|
+ ArrayList removeList = null;
|
|
|
+ ArrayList flushList = null;
|
|
|
+ int intPos;
|
|
|
+ long ticksNow;
|
|
|
|
|
|
- ticksNow = System.DateTime.Now.Ticks;
|
|
|
-
|
|
|
- intCachePos = 0;
|
|
|
+ ticksNow = DateTime.Now.Ticks;
|
|
|
|
|
|
+ intPos = 0;
|
|
|
// Lookup all items that needs to be removed, this is done in a two part
|
|
|
// operation to minimize the locking time.
|
|
|
- _lock.AcquireReaderLock(-1);
|
|
|
- try
|
|
|
- {
|
|
|
- arrCacheEntries = new CacheEntry[_intSize];
|
|
|
-
|
|
|
- intPos = 0;
|
|
|
- do
|
|
|
- {
|
|
|
- objEntry = _arrEntries[intPos];
|
|
|
- if (objEntry._objEntry != null)
|
|
|
+ _lock.AcquireReaderLock (-1);
|
|
|
+ try {
|
|
|
+ do {
|
|
|
+ objEntry = _arrEntries [intPos];
|
|
|
+ if (null != objEntry.Entry &&
|
|
|
+ ((objEntry.TicksExpires < ticksNow) || objEntry.Entry.ExpiresBucket != _byteID))
|
|
|
{
|
|
|
- if (objEntry._ticksExpires < ticksNow)
|
|
|
- {
|
|
|
- System.Threading.LockCookie ck = _lock.UpgradeToWriterLock(-1);
|
|
|
- try
|
|
|
- {
|
|
|
- //push the index for reuse
|
|
|
- _freeidx.Add(intPos);
|
|
|
- arrCacheEntries[intCachePos++] = objEntry._objEntry;
|
|
|
-
|
|
|
- objEntry._objEntry.ExpiresBucket = CacheEntry.NoBucketHash;
|
|
|
- objEntry._objEntry.ExpiresIndex = CacheEntry.NoIndexInBucket;
|
|
|
- objEntry._objEntry = null;
|
|
|
- _arrEntries [intPos] = objEntry;
|
|
|
- }
|
|
|
- finally
|
|
|
- {
|
|
|
- _lock.DowngradeFromWriterLock(ref ck);
|
|
|
- }
|
|
|
- }
|
|
|
+ if (null == removeList)
|
|
|
+ removeList = new ArrayList ();
|
|
|
+
|
|
|
+ removeList.Add (objEntry);
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
intPos++;
|
|
|
} while (intPos < _intSize);
|
|
|
}
|
|
|
- finally
|
|
|
- {
|
|
|
- _lock.ReleaseReaderLock();
|
|
|
- }
|
|
|
+ finally {
|
|
|
+ _lock.ReleaseReaderLock ();
|
|
|
+ }
|
|
|
+
|
|
|
+ if (null != removeList) {
|
|
|
+ flushList = new ArrayList (removeList.Count);
|
|
|
+
|
|
|
+ _lock.AcquireWriterLock (-1);
|
|
|
+ try {
|
|
|
+ foreach (ExpiresEntry entry in removeList) {
|
|
|
+ int id = entry.Entry.ExpiresIndex;
|
|
|
+
|
|
|
+ //push the index for reuse
|
|
|
+ _freeidx.Add (id);
|
|
|
+
|
|
|
+ if (entry.Entry.ExpiresBucket == _byteID) {
|
|
|
+ // add to our flush list
|
|
|
+ flushList.Add (entry.Entry);
|
|
|
+
|
|
|
+ // Remove from bucket
|
|
|
+ entry.Entry.ExpiresBucket = CacheEntry.NoBucketHash;
|
|
|
+ entry.Entry.ExpiresIndex = CacheEntry.NoIndexInBucket;
|
|
|
+ }
|
|
|
+
|
|
|
+ entry.Entry = null;
|
|
|
+
|
|
|
+ // Entries is structs, put it back
|
|
|
+ _arrEntries [id] = objEntry;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ finally {
|
|
|
+ _lock.ReleaseWriterLock ();
|
|
|
+ }
|
|
|
|
|
|
- // If we have any entries to remove, go ahead and call the cache manager remove.
|
|
|
- if (intCachePos > 0)
|
|
|
- {
|
|
|
- intPos = 0;
|
|
|
- do
|
|
|
- {
|
|
|
- _objManager.Remove(arrCacheEntries[intPos].Key, CacheItemRemovedReason.Expired);
|
|
|
+ // We can call this without locks, it can takes time due to callbacks to user code
|
|
|
+ foreach (CacheEntry entry in flushList)
|
|
|
+ _objManager.Remove (entry.Key, CacheItemRemovedReason.Expired);
|
|
|
|
|
|
- intPos++;
|
|
|
- } while (intPos < intCachePos);
|
|
|
+ flushList = null;
|
|
|
+ removeList = null;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
/// Returns the current size of the expires bucket.
|
|
|
/// </summary>
|
|
|
- internal int Size
|
|
|
- {
|
|
|
- get
|
|
|
- {
|
|
|
- //HACK: reuse the _intSize field!!! [DHC]
|
|
|
+ internal int Size {
|
|
|
+ get {
|
|
|
return _intSize;
|
|
|
}
|
|
|
}
|
|
|
@@ -332,10 +286,8 @@ namespace System.Web.Caching
|
|
|
/// <summary>
|
|
|
/// Returns number of items in the bucket.
|
|
|
/// </summary>
|
|
|
- internal int Count
|
|
|
- {
|
|
|
- get
|
|
|
- {
|
|
|
+ internal int Count {
|
|
|
+ get {
|
|
|
return _intCount;
|
|
|
}
|
|
|
}
|
|
|
@@ -379,9 +331,8 @@ namespace System.Web.Caching
|
|
|
/// An optimized collection for holding <see cref="Int32"/> values.
|
|
|
/// </summary>
|
|
|
[System.Serializable]
|
|
|
- private class Int32Collection : System.Collections.ICollection, System.Collections.IList, System.Collections.IEnumerable
|
|
|
- {
|
|
|
- #region Private vars & ctors
|
|
|
+ private class Int32Collection : System.Collections.ICollection, System.Collections.IList, System.Collections.IEnumerable {
|
|
|
+ #region Private vars & ctors
|
|
|
private const int DefaultMinimumCapacity = 16;
|
|
|
|
|
|
private System.Int32[] m_array = new System.Int32[DefaultMinimumCapacity];
|
|
|
@@ -389,36 +340,33 @@ namespace System.Web.Caching
|
|
|
private int m_version = 0;
|
|
|
|
|
|
/// <summary />
|
|
|
- public Int32Collection()
|
|
|
- { }
|
|
|
+ public Int32Collection() {
|
|
|
+ }
|
|
|
|
|
|
/// <summary />
|
|
|
- public Int32Collection(Int32Collection collection)
|
|
|
- { AddRange(collection); }
|
|
|
+ public Int32Collection(Int32Collection collection) {
|
|
|
+ AddRange(collection); }
|
|
|
|
|
|
/// <summary />
|
|
|
- public Int32Collection(System.Int32[] array)
|
|
|
- { AddRange(array); }
|
|
|
- #endregion
|
|
|
+ public Int32Collection(System.Int32[] array) {
|
|
|
+ AddRange(array); }
|
|
|
+ #endregion
|
|
|
|
|
|
- #region Public members
|
|
|
+ #region Public members
|
|
|
|
|
|
/// <summary />
|
|
|
- public int Count
|
|
|
- {
|
|
|
- get
|
|
|
- { return m_count; }
|
|
|
+ public int Count {
|
|
|
+ get {
|
|
|
+ return m_count; }
|
|
|
}
|
|
|
|
|
|
/// <summary />
|
|
|
- public void CopyTo(System.Int32[] array)
|
|
|
- {
|
|
|
+ public void CopyTo(System.Int32[] array) {
|
|
|
this.CopyTo(array, 0);
|
|
|
}
|
|
|
|
|
|
/// <summary />
|
|
|
- public void CopyTo(System.Int32[] array, int start)
|
|
|
- {
|
|
|
+ public void CopyTo(System.Int32[] array, int start) {
|
|
|
if (m_count > array.GetUpperBound(0)+1-start)
|
|
|
throw new System.ArgumentException("Destination array was not long enough.");
|
|
|
|
|
|
@@ -427,15 +375,12 @@ namespace System.Web.Caching
|
|
|
}
|
|
|
|
|
|
/// <summary />
|
|
|
- public System.Int32 this[int index]
|
|
|
- {
|
|
|
- get
|
|
|
- {
|
|
|
+ public System.Int32 this[int index] {
|
|
|
+ get {
|
|
|
ValidateIndex(index); // throws
|
|
|
return m_array[index];
|
|
|
}
|
|
|
- set
|
|
|
- {
|
|
|
+ set {
|
|
|
ValidateIndex(index); // throws
|
|
|
|
|
|
++m_version;
|
|
|
@@ -444,8 +389,7 @@ namespace System.Web.Caching
|
|
|
}
|
|
|
|
|
|
/// <summary />
|
|
|
- public int Add(System.Int32 item)
|
|
|
- {
|
|
|
+ public int Add(System.Int32 item) {
|
|
|
if (NeedsGrowth())
|
|
|
Grow();
|
|
|
|
|
|
@@ -456,22 +400,19 @@ namespace System.Web.Caching
|
|
|
}
|
|
|
|
|
|
/// <summary />
|
|
|
- public void Clear()
|
|
|
- {
|
|
|
+ public void Clear() {
|
|
|
++m_version;
|
|
|
m_array = new System.Int32[DefaultMinimumCapacity];
|
|
|
m_count = 0;
|
|
|
}
|
|
|
|
|
|
/// <summary />
|
|
|
- public bool Contains(System.Int32 item)
|
|
|
- {
|
|
|
+ public bool Contains(System.Int32 item) {
|
|
|
return ((IndexOf(item) == -1)?false:true);
|
|
|
}
|
|
|
|
|
|
/// <summary />
|
|
|
- public int IndexOf(System.Int32 item)
|
|
|
- {
|
|
|
+ public int IndexOf(System.Int32 item) {
|
|
|
for (int i=0; i < m_count; ++i)
|
|
|
if (m_array[i].Equals(item))
|
|
|
return i;
|
|
|
@@ -479,8 +420,7 @@ namespace System.Web.Caching
|
|
|
}
|
|
|
|
|
|
/// <summary />
|
|
|
- public void Insert(int position, System.Int32 item)
|
|
|
- {
|
|
|
+ public void Insert(int position, System.Int32 item) {
|
|
|
ValidateIndex(position,true); // throws
|
|
|
|
|
|
if (NeedsGrowth())
|
|
|
@@ -494,8 +434,7 @@ namespace System.Web.Caching
|
|
|
}
|
|
|
|
|
|
/// <summary />
|
|
|
- public void Remove(System.Int32 item)
|
|
|
- {
|
|
|
+ public void Remove(System.Int32 item) {
|
|
|
int index = IndexOf(item);
|
|
|
if (index < 0)
|
|
|
throw new System.ArgumentException("Cannot remove the specified item because it was not found in the specified Collection.");
|
|
|
@@ -504,8 +443,7 @@ namespace System.Web.Caching
|
|
|
}
|
|
|
|
|
|
/// <summary />
|
|
|
- public void RemoveAt(int index)
|
|
|
- {
|
|
|
+ public void RemoveAt(int index) {
|
|
|
ValidateIndex(index); // throws
|
|
|
|
|
|
++m_version;
|
|
|
@@ -519,12 +457,10 @@ namespace System.Web.Caching
|
|
|
// Public helpers (just to mimic some nice features of ArrayList)
|
|
|
|
|
|
/// <summary />
|
|
|
- public int Capacity
|
|
|
- {
|
|
|
- get
|
|
|
- { return m_array.Length; }
|
|
|
- set
|
|
|
- {
|
|
|
+ public int Capacity {
|
|
|
+ get {
|
|
|
+ return m_array.Length; }
|
|
|
+ set {
|
|
|
if (value < m_count) value = m_count;
|
|
|
if (value < DefaultMinimumCapacity) value = DefaultMinimumCapacity;
|
|
|
|
|
|
@@ -539,8 +475,7 @@ namespace System.Web.Caching
|
|
|
}
|
|
|
|
|
|
/// <summary />
|
|
|
- public void AddRange(Int32Collection collection)
|
|
|
- {
|
|
|
+ public void AddRange(Int32Collection collection) {
|
|
|
++m_version;
|
|
|
|
|
|
Capacity += collection.Count;
|
|
|
@@ -549,132 +484,111 @@ namespace System.Web.Caching
|
|
|
}
|
|
|
|
|
|
/// <summary />
|
|
|
- public void AddRange(System.Int32[] array)
|
|
|
- {
|
|
|
+ public void AddRange(System.Int32[] array) {
|
|
|
++m_version;
|
|
|
|
|
|
Capacity += array.Length;
|
|
|
System.Array.Copy(array, 0, this.m_array, m_count, array.Length);
|
|
|
m_count += array.Length;
|
|
|
}
|
|
|
- #endregion
|
|
|
+ #endregion
|
|
|
|
|
|
- #region Private helper methods
|
|
|
- private void ValidateIndex(int index)
|
|
|
- {
|
|
|
+ #region Private helper methods
|
|
|
+ private void ValidateIndex(int index) {
|
|
|
ValidateIndex(index,false);
|
|
|
}
|
|
|
|
|
|
- private void ValidateIndex(int index, bool allowEqualEnd)
|
|
|
- {
|
|
|
+ private void ValidateIndex(int index, bool allowEqualEnd) {
|
|
|
int max = (allowEqualEnd)?(m_count):(m_count-1);
|
|
|
if (index < 0 || index > max)
|
|
|
throw new System.ArgumentOutOfRangeException("Index was out of range. Must be non-negative and less than the size of the collection.", (object)index, "Specified argument was out of the range of valid values.");
|
|
|
}
|
|
|
|
|
|
- private bool NeedsGrowth()
|
|
|
- {
|
|
|
+ private bool NeedsGrowth() {
|
|
|
return (m_count >= Capacity);
|
|
|
}
|
|
|
|
|
|
- private void Grow()
|
|
|
- {
|
|
|
+ private void Grow() {
|
|
|
if (NeedsGrowth())
|
|
|
Capacity = m_count*2;
|
|
|
}
|
|
|
|
|
|
- private bool NeedsTrimming()
|
|
|
- {
|
|
|
+ private bool NeedsTrimming() {
|
|
|
return (m_count <= Capacity/2);
|
|
|
}
|
|
|
|
|
|
- private void Trim()
|
|
|
- {
|
|
|
+ private void Trim() {
|
|
|
if (NeedsTrimming())
|
|
|
Capacity = m_count;
|
|
|
}
|
|
|
- #endregion
|
|
|
+ #endregion
|
|
|
|
|
|
- #region System.Collections.ICollection implementation
|
|
|
- bool System.Collections.ICollection.IsSynchronized
|
|
|
- {
|
|
|
- get
|
|
|
- { return m_array.IsSynchronized; }
|
|
|
+ #region System.Collections.ICollection implementation
|
|
|
+ bool System.Collections.ICollection.IsSynchronized {
|
|
|
+ get {
|
|
|
+ return m_array.IsSynchronized; }
|
|
|
}
|
|
|
|
|
|
- object System.Collections.ICollection.SyncRoot
|
|
|
- {
|
|
|
- get
|
|
|
- { return m_array.SyncRoot; }
|
|
|
+ object System.Collections.ICollection.SyncRoot {
|
|
|
+ get {
|
|
|
+ return m_array.SyncRoot; }
|
|
|
}
|
|
|
|
|
|
- void System.Collections.ICollection.CopyTo(System.Array array, int start)
|
|
|
- {
|
|
|
+ void System.Collections.ICollection.CopyTo(System.Array array, int start) {
|
|
|
this.CopyTo((System.Int32[])array, start);
|
|
|
}
|
|
|
- #endregion
|
|
|
+ #endregion
|
|
|
|
|
|
- #region System.Collections.IList implementation
|
|
|
- bool System.Collections.IList.IsFixedSize
|
|
|
- {
|
|
|
- get
|
|
|
- { return false; }
|
|
|
+ #region System.Collections.IList implementation
|
|
|
+ bool System.Collections.IList.IsFixedSize {
|
|
|
+ get {
|
|
|
+ return false; }
|
|
|
}
|
|
|
|
|
|
- bool System.Collections.IList.IsReadOnly
|
|
|
- {
|
|
|
- get
|
|
|
- { return false; }
|
|
|
+ bool System.Collections.IList.IsReadOnly {
|
|
|
+ get {
|
|
|
+ return false; }
|
|
|
}
|
|
|
|
|
|
- object System.Collections.IList.this[int index]
|
|
|
- {
|
|
|
+ object System.Collections.IList.this[int index] {
|
|
|
get { return (object)this[index]; }
|
|
|
set { this[index] = (System.Int32)value; }
|
|
|
}
|
|
|
|
|
|
- int System.Collections.IList.Add(object item)
|
|
|
- {
|
|
|
+ int System.Collections.IList.Add(object item) {
|
|
|
return this.Add((System.Int32)item);
|
|
|
}
|
|
|
|
|
|
- bool System.Collections.IList.Contains(object item)
|
|
|
- {
|
|
|
+ bool System.Collections.IList.Contains(object item) {
|
|
|
return this.Contains((System.Int32)item);
|
|
|
}
|
|
|
|
|
|
- int System.Collections.IList.IndexOf(object item)
|
|
|
- {
|
|
|
+ int System.Collections.IList.IndexOf(object item) {
|
|
|
return this.IndexOf((System.Int32)item);
|
|
|
}
|
|
|
|
|
|
- void System.Collections.IList.Insert(int position, object item)
|
|
|
- {
|
|
|
+ void System.Collections.IList.Insert(int position, object item) {
|
|
|
this.Insert(position, (System.Int32)item);
|
|
|
}
|
|
|
|
|
|
- void System.Collections.IList.Remove(object item)
|
|
|
- {
|
|
|
+ void System.Collections.IList.Remove(object item) {
|
|
|
this.Remove((System.Int32)item);
|
|
|
}
|
|
|
- #endregion
|
|
|
+ #endregion
|
|
|
|
|
|
- #region System.Collections.IEnumerable and enumerator implementation
|
|
|
+ #region System.Collections.IEnumerable and enumerator implementation
|
|
|
/// <summary />
|
|
|
- public Enumerator GetEnumerator()
|
|
|
- {
|
|
|
+ public Enumerator GetEnumerator() {
|
|
|
return new Enumerator(this);
|
|
|
}
|
|
|
|
|
|
- System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
|
|
|
- {
|
|
|
+ System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() {
|
|
|
return GetEnumerator();
|
|
|
}
|
|
|
|
|
|
// Nested enumerator class
|
|
|
/// <summary />
|
|
|
- public class Enumerator : System.Collections.IEnumerator
|
|
|
- {
|
|
|
+ public class Enumerator : System.Collections.IEnumerator {
|
|
|
private Int32Collection m_collection;
|
|
|
private int m_index;
|
|
|
private int m_version;
|
|
|
@@ -682,23 +596,20 @@ namespace System.Web.Caching
|
|
|
// Construction
|
|
|
|
|
|
/// <summary />
|
|
|
- public Enumerator(Int32Collection tc)
|
|
|
- {
|
|
|
+ public Enumerator(Int32Collection tc) {
|
|
|
m_collection = tc;
|
|
|
m_index = -1;
|
|
|
m_version = tc.m_version;
|
|
|
}
|
|
|
|
|
|
/// <summary />
|
|
|
- public System.Int32 Current
|
|
|
- {
|
|
|
- get
|
|
|
- { return m_collection[m_index]; }
|
|
|
+ public System.Int32 Current {
|
|
|
+ get {
|
|
|
+ return m_collection[m_index]; }
|
|
|
}
|
|
|
|
|
|
/// <summary />
|
|
|
- public bool MoveNext()
|
|
|
- {
|
|
|
+ public bool MoveNext() {
|
|
|
if (m_version != m_collection.m_version)
|
|
|
throw new System.InvalidOperationException("Collection was modified; enumeration operation may not execute.");
|
|
|
|
|
|
@@ -707,22 +618,21 @@ namespace System.Web.Caching
|
|
|
}
|
|
|
|
|
|
/// <summary />
|
|
|
- public void Reset()
|
|
|
- {
|
|
|
+ public void Reset() {
|
|
|
if (m_version != m_collection.m_version)
|
|
|
throw new System.InvalidOperationException("Collection was modified; enumeration operation may not execute.");
|
|
|
|
|
|
m_index = -1;
|
|
|
}
|
|
|
|
|
|
- object System.Collections.IEnumerator.Current
|
|
|
- {
|
|
|
- get
|
|
|
- { return (object)(this.Current); }
|
|
|
+ object System.Collections.IEnumerator.Current {
|
|
|
+ get {
|
|
|
+ return (object)(this.Current); }
|
|
|
}
|
|
|
}
|
|
|
- #endregion
|
|
|
+ #endregion
|
|
|
}
|
|
|
#endregion
|
|
|
}
|
|
|
}
|
|
|
+
|