using CommonLang.Concurrent; using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Text; namespace CommonLang { public static class ObjectPoolStatus { internal static AtomicLong s_total_count = new AtomicLong(0); internal static AtomicLong s_total_inactive = new AtomicLong(0); public static long TotalCount { get { return s_total_count.Value; } } public static long TotalInactive { get { return s_total_inactive.Value; } } public static long TotalActive { get { return TotalCount - TotalInactive; } } } public class ObjectPool { public delegate T ActionCreater(); private readonly Stack m_Stack = new Stack(); private readonly ActionCreater m_ActionOnCreate; private readonly Action m_ActionOnGet; private readonly Action m_ActionOnRelease; private AtomicLong count = new AtomicLong(0); public long countAll { get { return count.Value; } } public long countInactive { get { return this.m_Stack.Count; } } public long countActive { get { return this.countAll - this.countInactive; } } public ObjectPool(ActionCreater actionCreate = null, Action actionOnGet = null, Action actionOnRelease = null) { this.m_ActionOnGet = actionOnGet; this.m_ActionOnRelease = actionOnRelease; this.m_ActionOnCreate = actionCreate; } public T Get() { lock (this) { T t; if (this.m_Stack.Count == 0) { if (m_ActionOnCreate != null) { t = m_ActionOnCreate(); } else { t = ((default(T) == null) ? Activator.CreateInstance() : default(T)); } this.count++; ObjectPoolStatus.s_total_count++; } else { t = this.m_Stack.Pop(); ObjectPoolStatus.s_total_inactive--; } if (this.m_ActionOnGet != null) { this.m_ActionOnGet(t); } return t; } } public void Release(T element) { lock (this) { if (this.m_Stack.Count > 0 && object.ReferenceEquals(this.m_Stack.Peek(), element)) { throw new Exception("Internal error. Trying to destroy object that is already released to pool."); } if (this.m_ActionOnRelease != null) { this.m_ActionOnRelease(element); } this.m_Stack.Push(element); ObjectPoolStatus.s_total_inactive++; } } } public static class ListObjectPool { private static readonly ObjectPool> s_ListPool = new ObjectPool>(s_ListPool_OnCreate, null, s_ListPool_OnRelease); private static List s_ListPool_OnCreate() { return new AutoReleaseList(); } private static void s_ListPool_OnRelease(List l) { l.Clear(); } public static AutoReleaseList AllocAutoRelease() { AutoReleaseList ret = s_ListPool.Get() as AutoReleaseList; return ret; } public static AutoReleaseList AllocAutoRelease(IEnumerable added) { AutoReleaseList ret = s_ListPool.Get() as AutoReleaseList; if (added != null) { ret.AddRange(added); } return ret; } public static AutoReleaseList AllocAutoRelease(T[] added) { AutoReleaseList ret = s_ListPool.Get() as AutoReleaseList; if (added != null) { ret.AddRange(added); } return ret; } public static AutoReleaseList AllocAutoRelease(int capacity) { AutoReleaseList ret = s_ListPool.Get() as AutoReleaseList; if (capacity != 0) { ret.Capacity = capacity; } return ret; } public static void Release(List toRelease) { s_ListPool.Release(toRelease); } public class AutoReleaseList : List, IDisposable { internal AutoReleaseList() { } void IDisposable.Dispose() { ListObjectPool.Release(this); } } } public static class MemoryStreamObjectPool { private static readonly ObjectPool s_Pool = new ObjectPool(s_ListPool_OnCreate, null, null); private static AutoRelease s_ListPool_OnCreate() { return new AutoRelease(); } public static AutoRelease AllocAutoRelease() { AutoRelease ret = s_Pool.Get() as AutoRelease; return ret; } public static AutoRelease AllocAutoRelease(int capacity) { AutoRelease ret = s_Pool.Get() as AutoRelease; ret.Capacity = capacity; return ret; } public static AutoRelease AllocAutoRelease(byte[] buffer) { AutoRelease ret = s_Pool.Get() as AutoRelease; IO.IOUtil.WriteToEnd(ret, buffer, 0, buffer.Length); ret.Position = 0; return ret; } public static AutoRelease AllocAutoRelease(byte[] buffer, int offset, int length) { AutoRelease ret = s_Pool.Get() as AutoRelease; IO.IOUtil.WriteToEnd(ret, buffer, offset, length); ret.Position = 0; return ret; } public static void Release(AutoRelease toRelease) { s_Pool.Release(toRelease); } public class AutoRelease : MemoryStream { internal AutoRelease() { } protected override void Dispose(bool disposing) { this.Position = 0; this.SetLength(0); MemoryStreamObjectPool.Release(this); } } } }