using System; using System.Collections.Generic; using System.Threading; namespace NetWorkHelper.ICollections { /// /// 有序的数组,SortedArray 中的元素是不允许重复的。如果添加数组中已经存在的元素,将会被忽略。 /// 该实现是线程安全的。 /// [Serializable] public class SortedArray : SortedArray2, IComparer where T : IComparable { public SortedArray() { base.comparer4Key = this; } public SortedArray(ICollection collection) { base.comparer4Key = this; base.Rebuild(collection); } #region IComparer 成员 public int Compare(T x, T y) { return x.CompareTo(y); } #endregion } /// /// 有序的数组,SortedArray 中的元素是不允许重复的。如果添加数组中已经存在的元素,将会被忽略。 /// 该实现是线程安全的。 /// [Serializable] public class SortedArray2 { private List lazyCopy = null; private int minCapacityForShrink = 32; private T[] array = new T[32]; private int validCount = 0; protected IComparer 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 comparer) { this.comparer4Key = comparer; } public SortedArray2(IComparer comparer, ICollection collection) { this.comparer4Key = comparer; Rebuild(collection); } protected void Rebuild(ICollection 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(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); } /// /// Add 将一个元素添加到数组中。如果数组中已存在目标元素,则忽略。无论哪种情况,posIndex都会被赋予正确的值。 /// 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(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 collection) { this.Add(collection, true); } /// /// Add 如果能保证collection中的元素不会与现有的元素重复,则checkRepeat可以传入false。 /// public void Add(ICollection collection, bool checkRepeat) { if (collection == null || collection.Count == 0) { return; } using (this.SmartRWLocker.Lock(AccessMode.Write)) { ICollection resultCollection = collection; #region checkRepeat if (checkRepeat) { Dictionary dic = new Dictionary(); 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(this.array, 0, this.validCount, this.comparer4Key); } this.lazyCopy = null; } #endregion #region Remove #region Remove /// /// Remove 删除数组中所有值为t的元素。 /// 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 /// /// Shrink 将内部数组收缩到最小,释放内存。 /// 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 GetAll() { List list = new List(); using (this.SmartRWLocker.Lock(AccessMode.Read)) { for (int i = 0; i < this.validCount; i++) { list.Add(this.array[i]); } } return list; } #endregion #region GetAllReadonly /// /// 注意,内部使用了Lazy缓存,返回的集合不可被修改。 /// public List GetAllReadonly() { if (this.lazyCopy != null) { return this.lazyCopy; } using (this.SmartRWLocker.Lock(AccessMode.Read)) { List list = new List(); 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 } /// /// SmartRWLocker 简化了ReaderWriterLock的使用。通过using来使用Lock方法返回的对象,如:using(this.smartLocker.Lock(AccessMode.Read)){...} /// zhuweisky 2008.11.25 /// 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 } /// /// LockingObject SmartRWLocker的Lock方法返回的锁对象。仅仅通过using来使用该对象,如:using(this.smartLocker.Lock(AccessMode.Read)){...} /// 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 } /// /// AccessMode 访问锁定资源的方式。 /// public enum AccessMode { Read = 0, Write, /// /// 前提条件:已经获取Read锁。 /// 再采用此模式,可以先升级到Write,访问资源,再降级回Read。 /// UpAndDowngrade4Write } }