现在的位置: 首页 > 综合 > 正文

自己写的ObjectPool类谨供参考学习。。。

2012年08月12日 ⁄ 综合 ⁄ 共 5189字 ⁄ 字号 评论关闭
#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

抱歉!评论已关闭.