Files
huabe-sitondao/tongxin/NetWorkHelper/ICollections/SortedArray.cs
2025-11-14 16:12:32 +08:00

672 lines
17 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using System;
using System.Collections.Generic;
using System.Threading;
namespace NetWorkHelper.ICollections
{
/// <summary>
/// 有序的数组SortedArray 中的元素是不允许重复的。如果添加数组中已经存在的元素,将会被忽略。
/// 该实现是线程安全的。
/// </summary>
[Serializable]
public class SortedArray<T> : SortedArray2<T>, IComparer<T> where T : IComparable
{
public SortedArray()
{
base.comparer4Key = this;
}
public SortedArray(ICollection<T> collection)
{
base.comparer4Key = this;
base.Rebuild(collection);
}
#region IComparer<TKey>
public int Compare(T x, T y)
{
return x.CompareTo(y);
}
#endregion
}
/// <summary>
/// 有序的数组SortedArray 中的元素是不允许重复的。如果添加数组中已经存在的元素,将会被忽略。
/// 该实现是线程安全的。
/// </summary>
[Serializable]
public class SortedArray2<T>
{
private List<T> lazyCopy = null;
private int minCapacityForShrink = 32;
private T[] array = new T[32];
private int validCount = 0;
protected IComparer<T> comparer4Key = null;
#region SmartRWLocker
[NonSerialized] private SmartRWLocker smartRWLocker = new SmartRWLocker();
private SmartRWLocker SmartRWLocker
{
get
{
if (smartRWLocker == null)
{
smartRWLocker = new SmartRWLocker();
}
return smartRWLocker;
}
}
#endregion
#region Ctor
protected SortedArray2()
{
}
public SortedArray2(IComparer<T> comparer)
{
this.comparer4Key = comparer;
}
public SortedArray2(IComparer<T> comparer, ICollection<T> collection)
{
this.comparer4Key = comparer;
Rebuild(collection);
}
protected void Rebuild(ICollection<T> collection)
{
if (collection == null || collection.Count == 0)
{
return;
}
this.array = new T[collection.Count];
collection.CopyTo(this.array, 0);
Array.Sort(this.array, this.comparer4Key);
this.validCount = collection.Count;
}
#endregion
#region Property
#region Count
public int Count
{
get { return this.validCount; }
}
#endregion
#region Capacity
private int Capacity
{
get { return this.array.Length; }
}
#endregion
#region LastReadTime
public DateTime LastReadTime
{
get { return this.SmartRWLocker.LastRequireReadTime; }
}
#endregion
#region LastWriteTime
public DateTime LastWriteTime
{
get { return this.SmartRWLocker.LastRequireWriteTime; }
}
#endregion
#endregion
#region Contains
public bool Contains(T t)
{
return this.IndexOf(t) >= 0;
}
#endregion
#region Index
public T this[int index]
{
get
{
using (this.SmartRWLocker.Lock(AccessMode.Read))
{
if (index < 0 || (index >= this.validCount))
{
throw new Exception("Index out of the range !");
}
return this.array[index];
}
}
}
#endregion
#region IndexOf
public int IndexOf(T t)
{
using (this.SmartRWLocker.Lock(AccessMode.Read))
{
if (this.validCount == 0)
{
return -1;
}
int index = Array.BinarySearch<T>(this.array, 0, this.validCount, t, this.comparer4Key);
return (index < 0) ? -1 : index;
}
}
#endregion
#region Add
public void Add(T t)
{
int posIndex = 0;
this.Add(t, out posIndex);
}
/// <summary>
/// Add 将一个元素添加到数组中。如果数组中已存在目标元素则忽略。无论哪种情况posIndex都会被赋予正确的值。
/// </summary>
public void Add(T t, out int posIndex)
{
if (t == null)
{
throw new Exception("Target can't be null !");
}
using (this.SmartRWLocker.Lock(AccessMode.Write))
{
int index = Array.BinarySearch<T>(this.array, 0, this.validCount, t, this.comparer4Key);
if (index >= 0)
{
posIndex = index;
return;
}
this.AdjustCapacity(1);
posIndex = ~index;
Array.Copy(this.array, posIndex, this.array, posIndex + 1, this.validCount - posIndex);
this.array[posIndex] = t;
++this.validCount;
}
this.lazyCopy = null;
}
public void Add(ICollection<T> collection)
{
this.Add(collection, true);
}
/// <summary>
/// Add 如果能保证collection中的元素不会与现有的元素重复则checkRepeat可以传入false。
/// </summary>
public void Add(ICollection<T> collection, bool checkRepeat)
{
if (collection == null || collection.Count == 0)
{
return;
}
using (this.SmartRWLocker.Lock(AccessMode.Write))
{
ICollection<T> resultCollection = collection;
#region checkRepeat
if (checkRepeat)
{
Dictionary<T, T> dic = new Dictionary<T, T>();
foreach (T t in collection)
{
if (dic.ContainsKey(t) || this.Contains(t))
{
continue;
}
dic.Add(t, t);
}
resultCollection = dic.Keys;
}
#endregion
if (resultCollection.Count == 0)
{
return;
}
this.AdjustCapacity(resultCollection.Count);
foreach (T t in resultCollection)
{
this.array[this.validCount] = t;
++this.validCount;
}
Array.Sort<T>(this.array, 0, this.validCount, this.comparer4Key);
}
this.lazyCopy = null;
}
#endregion
#region Remove
#region Remove
/// <summary>
/// Remove 删除数组中所有值为t的元素。
/// </summary>
public void Remove(T t)
{
if (t == null)
{
return;
}
int index = -1;
do
{
index = this.IndexOf(t);
if (index >= 0)
{
this.RemoveAt(index);
}
} while (index >= 0);
this.lazyCopy = null;
}
#endregion
#region RemoveAt
public void RemoveAt(int index)
{
using (this.SmartRWLocker.Lock(AccessMode.Write))
{
if (index < 0 || (index >= this.validCount))
{
return;
}
if (index == this.validCount - 1)
{
this.array[index] = default(T);
}
else
{
Array.Copy(this.array, index + 1, this.array, index, this.validCount - index - 1);
}
--this.validCount;
}
this.lazyCopy = null;
}
#endregion
#region RemoveBetween
public void RemoveBetween(int minIndex, int maxIndex)
{
using (this.SmartRWLocker.Lock(AccessMode.Write))
{
minIndex = minIndex < 0 ? 0 : minIndex;
maxIndex = maxIndex >= this.validCount ? this.validCount - 1 : maxIndex;
if (maxIndex < minIndex)
{
return;
}
Array.Copy(this.array, maxIndex + 1, this.array, minIndex, this.validCount - maxIndex - 1);
this.validCount -= (maxIndex - minIndex + 1);
}
this.lazyCopy = null;
}
#endregion
#endregion
#region GetBetween
public T[] GetBetween(int minIndex, int maxIndex)
{
using (this.SmartRWLocker.Lock(AccessMode.Read))
{
minIndex = minIndex < 0 ? 0 : minIndex;
maxIndex = maxIndex >= this.validCount ? this.validCount - 1 : maxIndex;
if (maxIndex < minIndex)
{
return new T[0];
}
int count = maxIndex - minIndex - 1;
T[] result = new T[count];
Array.Copy(this.array, minIndex, result, 0, count);
return result;
}
}
#endregion
#region Shrink
/// <summary>
/// Shrink 将内部数组收缩到最小,释放内存。
/// </summary>
public void Shrink()
{
using (this.SmartRWLocker.Lock(AccessMode.Write))
{
if (this.array.Length == this.validCount)
{
return;
}
int len = this.validCount >= this.minCapacityForShrink ? this.validCount : this.minCapacityForShrink;
T[] newAry = new T[len];
Array.Copy(this.array, 0, newAry, 0, this.validCount);
this.array = newAry;
}
}
#endregion
#region AdjustCapacity
private void AdjustCapacity(int newCount)
{
using (this.SmartRWLocker.Lock(AccessMode.Write))
{
int totalCount = this.validCount + newCount;
if (this.array.Length >= totalCount)
{
return;
}
int newCapacity = this.array.Length;
while (newCapacity < totalCount)
{
newCapacity *= 2;
}
T[] newAry = new T[newCapacity];
Array.Copy(this.array, 0, newAry, 0, this.validCount);
this.array = newAry;
}
}
#endregion
#region GetMax
public T GetMax()
{
using (this.SmartRWLocker.Lock(AccessMode.Read))
{
if (this.validCount == 0)
{
throw new Exception("SortedArray is Empty !");
}
return this.array[this.validCount - 1];
}
}
#endregion
#region GetMin
public T GetMin()
{
using (this.SmartRWLocker.Lock(AccessMode.Read))
{
if (this.validCount == 0)
{
throw new Exception("SortedArray is Empty !");
}
return this.array[0];
}
}
#endregion
#region GetAll
public List<T> GetAll()
{
List<T> list = new List<T>();
using (this.SmartRWLocker.Lock(AccessMode.Read))
{
for (int i = 0; i < this.validCount; i++)
{
list.Add(this.array[i]);
}
}
return list;
}
#endregion
#region GetAllReadonly
/// <summary>
/// 注意内部使用了Lazy缓存返回的集合不可被修改。
/// </summary>
public List<T> GetAllReadonly()
{
if (this.lazyCopy != null)
{
return this.lazyCopy;
}
using (this.SmartRWLocker.Lock(AccessMode.Read))
{
List<T> list = new List<T>();
for (int i = 0; i < this.validCount; i++)
{
list.Add(this.array[i]);
}
this.lazyCopy = list;
return this.lazyCopy;
}
}
#endregion
#region Clear
public void Clear()
{
using (this.SmartRWLocker.Lock(AccessMode.Write))
{
this.array = new T[this.minCapacityForShrink];
this.validCount = 0;
}
this.lazyCopy = null;
}
#endregion
#region ToString
public override string ToString()
{
return string.Format("Count:{0} ,Capacity:{1}", this.validCount, this.array.Length);
}
#endregion
}
/// <summary>
/// SmartRWLocker 简化了ReaderWriterLock的使用。通过using来使用Lock方法返回的对象using(this.smartLocker.Lock(AccessMode.Read)){...}
/// zhuweisky 2008.11.25
/// </summary>
public class SmartRWLocker
{
private ReaderWriterLock readerWriterLock = new ReaderWriterLock();
#region LastRequireReadTime
private DateTime lastRequireReadTime = DateTime.Now;
public DateTime LastRequireReadTime
{
get { return lastRequireReadTime; }
}
#endregion
#region LastRequireWriteTime
private DateTime lastRequireWriteTime = DateTime.Now;
public DateTime LastRequireWriteTime
{
get { return lastRequireWriteTime; }
}
#endregion
#region Lock
public LockingObject Lock(AccessMode accessMode, bool enableSynchronize)
{
if (!enableSynchronize)
{
return null;
}
return this.Lock(accessMode);
}
public LockingObject Lock(AccessMode accessMode)
{
if (accessMode == AccessMode.Read)
{
this.lastRequireReadTime = DateTime.Now;
}
else
{
this.lastRequireWriteTime = DateTime.Now;
}
return new LockingObject(this.readerWriterLock, accessMode);
}
#endregion
}
/// <summary>
/// LockingObject SmartRWLocker的Lock方法返回的锁对象。仅仅通过using来使用该对象using(this.smartLocker.Lock(AccessMode.Read)){...}
/// </summary>
public class LockingObject : IDisposable
{
private ReaderWriterLock readerWriterLock;
private AccessMode accessMode = AccessMode.Read;
private LockCookie lockCookie;
#region Ctor
public LockingObject(ReaderWriterLock _lock, AccessMode _lockMode)
{
this.readerWriterLock = _lock;
this.accessMode = _lockMode;
if (this.accessMode == AccessMode.Read)
{
this.readerWriterLock.AcquireReaderLock(-1);
}
else if (this.accessMode == AccessMode.Write)
{
this.readerWriterLock.AcquireWriterLock(-1);
}
else //UpAndDowngrade
{
this.lockCookie = this.readerWriterLock.UpgradeToWriterLock(-1);
}
}
#endregion
#region IDisposable
public void Dispose()
{
if (this.accessMode == AccessMode.Read)
{
this.readerWriterLock.ReleaseReaderLock();
}
else if (this.accessMode == AccessMode.Write)
{
this.readerWriterLock.ReleaseWriterLock();
}
else //UpAndDowngrade
{
this.readerWriterLock.DowngradeFromWriterLock(ref this.lockCookie);
}
}
#endregion
}
/// <summary>
/// AccessMode 访问锁定资源的方式。
/// </summary>
public enum AccessMode
{
Read = 0,
Write,
/// <summary>
/// 前提条件已经获取Read锁。
/// 再采用此模式可以先升级到Write访问资源再降级回Read。
/// </summary>
UpAndDowngrade4Write
}
}