自己写的ObjectPool类谨供参考学习。。。
2011-03-11 14:55
218 查看
#region Delegate public delegate T LookupItem<T>(); public delegate void ReleaseItem<T>(T item); #endregion #region ObjectPool public class ObjectPool<T> : IPool<T>, IFreeness where T : class { #region NestedTypes internal struct LIFOEntry { public bool Idle; public DateTime CreateTime; public T Value; } #endregion #region StaticMembers public const int DefaultMinSize = 2; public const int DefaultMaxSize = 100; internal static readonly bool IsSubOfIDisposable; static ObjectPool() { IsSubOfIDisposable = typeof(T).IsSubclassOf(typeof(IDisposable)); } #endregion #region Fields private WeakEvent<EventHandler> eventFull; private LookupItem<T> lookupItem; private ReleaseItem<T> releaseItem; private TimeSpan lifeTime; private int minSize, maxSize, offset, freeTimeout; private GCHandle[] weakHandle; private LIFOEntry[] container; private ReaderWriterLockSlim locker; #endregion #region Properties public event EventHandler Full { add { if (eventFull == null) { Interlocked.CompareExchange(ref eventFull, new WeakEvent<EventHandler>(), null); } eventFull.Add(value); } remove { if (eventFull != null) { eventFull.Remove(value); } } } public TimeSpan LifeTime { get { return lifeTime; } } int IFreeness.Capacity { get { return maxSize; } } public int MinSize { get { return minSize; } } public int MaxSize { get { return maxSize; } } public int Size { get { return offset + 1; } } public bool IsFull { get { return offset + 1 == maxSize; } } public int FreeTimeout { set { Interlocked.Exchange(ref freeTimeout, value); } get { return freeTimeout; } } #endregion #region Constructor public ObjectPool(LookupItem<T> createDelegate, ReleaseItem<T> releaseDelegate, TimeSpan timeout) : this(createDelegate, releaseDelegate, Freer.LifeTime, DefaultMinSize, DefaultMaxSize) { } public ObjectPool(LookupItem<T> lookupDelegate, ReleaseItem<T> releaseDelegate, TimeSpan timeout, int min, int max) { AppDiag.GuardArgument(lookupDelegate, "lookupDelegate"); T t1 = lookupDelegate(), t2 = lookupDelegate(); AppDiag.GuardArgument(object.ReferenceEquals(t1, t2), "Lookup delegate can't return the same reference object."); lookupItem = lookupDelegate; releaseItem = releaseDelegate; lifeTime = timeout; AppDiag.GuardArgument(min < 0, "The min size must > -1."); AppDiag.GuardArgument(max < 2, "The max size must > 1."); minSize = min; maxSize = max; freeTimeout = 2000; weakHandle = new GCHandle[max / 10]; GCHandle emptyHandle = GCHandle.Alloc(null, GCHandleType.Weak); for (int i = 0; i < weakHandle.Length; i++) { weakHandle[i] = emptyHandle; } container = new LIFOEntry[maxSize]; container[0].Idle = container[1].Idle = true; container[0].CreateTime = container[1].CreateTime = DateTime.UtcNow; container[0].Value = t1; container[1].Value = t2; offset++; locker = new ReaderWriterLockSlim(); Freer.Instance.Add(this); } #endregion #region Methods public void Store(T item) { if (releaseItem != null) { releaseItem(item); } locker.EnterUpgradeableReadLock(); try { int index = -1; for (int i = offset; i > 0; i--) { if (container[i].Value.Equals(item)) { locker.EnterWriteLock(); try { container[i].Idle = true; } finally { locker.ExitWriteLock(); } index = i; break; } } if (index == -1) { locker.EnterWriteLock(); try { if (offset + 1 == maxSize && (eventFull == null || !eventFull.Raise(this, EventArgs.Empty))) { throw new PoolFullException(); } container[offset].Idle = true; container[offset].CreateTime = DateTime.UtcNow; container[offset++].Value = item; } finally { locker.ExitWriteLock(); } } } finally { locker.ExitUpgradeableReadLock(); } } public T Retrieve() { T item = null; locker.EnterReadLock(); try { for (int i = 0; i < weakHandle.Length; i++) { if (weakHandle[i].Target != null) { item = (T)weakHandle[i].Target; weakHandle[i].Target = null; break; } } } finally { locker.ExitReadLock(); } if (item == null) { locker.EnterUpgradeableReadLock(); try { if (offset + 1 == maxSize && (eventFull == null || !eventFull.Raise(this, EventArgs.Empty))) { throw new PoolFullException(); } for (int i = offset; i > 0; i--) { if (container[i].Idle) { locker.EnterWriteLock(); try { container[i].Idle = false; } finally { locker.ExitWriteLock(); } item = container[i].Value; break; } } if (item == null) { locker.EnterWriteLock(); try { container[offset].Idle = false; container[offset].CreateTime = DateTime.UtcNow; item = container[offset++].Value = lookupItem(); } finally { locker.ExitWriteLock(); } } } finally { locker.ExitUpgradeableReadLock(); } } return item; } public int Free() { int freed = 0; if (lifeTime != TimeSpan.Zero && offset > minSize - 1) { if (locker.TryEnterWriteLock(freeTimeout)) { try { LIFOEntry entry; if (IsSubOfIDisposable) { List<T> list = new List<T>(); for (int i = 0; i <= offset; i++) { entry = container[i]; if (DateTime.UtcNow - entry.CreateTime >= lifeTime) { if (entry.Idle) { list.Add(container[i].Value); } int j = i; while (j < offset) { entry = container[j]; int nextJ = ++j; container[j] = container[nextJ]; container[nextJ] = entry; } for (j = 0; j < weakHandle.Length; j++) { if (weakHandle[i].Target == null) { weakHandle[i].Target = container[offset].Value; container[offset].Value = null; break; } } freed++; if (offset-- <= minSize) { break; } } } list.ForEach(item => ((IDisposable)item).Dispose()); } else { for (int i = 0; i <= offset; i++) { entry = container[i]; if (DateTime.UtcNow - entry.CreateTime >= lifeTime) { int j = i; while (j < offset) { entry = container[j]; int nextJ = ++j; container[j] = container[nextJ]; container[nextJ] = entry; } for (j = 0; j < weakHandle.Length; j++) { if (weakHandle[i].Target == null) { weakHandle[i].Target = container[offset].Value; container[offset].Value = null; break; } } freed++; if (offset-- <= minSize) { break; } } } } } finally { locker.ExitWriteLock(); } } } return freed; } #endregion } #endregion #region PoolFullException public class PoolFullException : Exception { public PoolFullException() : base("Object Pool is Full.") { } public PoolFullException(string msg) : base(msg) { } } #endregion
相关文章推荐
- 开始学习Matlab,一点一滴记录自己的所学 仅供自己参考Matlab(2)
- ipbale 常用指令(供自己学习参考,如果有错请大侠们指出)
- Java:有关try、catch和finally的学习(供自己参考)
- Calendar类学习,自己写了个日历查询小程序,供大家学习参考
- log4j学习_仅供自己参考
- urlrewrite学习_仅供自己参考
- Android:有关菜单的学习(供自己参考)
- proxool学习_仅供自己参考
- Android:有关下拉菜单导航的学习(供自己参考)
- 学习XMPP,比较好的参考文章的地址,留着自己好找
- struts重复提交学习_仅供自己参考
- 在做mes系统时,利用D7 IdMessage&IdSMTP发送邮件,从盒子上学习了不少的东西,自己整理了一下,想share给新手,学习参考!
- 开始学习Matlab,一点一滴记录自己的所学 仅供个人参考Matlab(1)
- 我的安卓学习的总结(持续补充,供自己参考)
- 这里将长期更新一些算法小练习,供自己和同行学习和参考
- 只学一点点:我的技术学习策略(虽然不赞同,但可以参考一下,针对不常用的技术可以这样,同时可以:寻找遁去的一,不用管别人怎么想;有学习的时间,不如自己写、自己实践,否则学完了都不知道是什么东西)
- [系列]OS学习-自己写操作系统(4)- 保护模式
- 自己构造IRP包来实现驱动与驱动之间的通信(成功笔记下来以后参考用)
- 自定义view学习-创建自己的九宫格解锁view
- 《UNIX环境高级编程》学习笔记--第三章习题2参考答案