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

C# LIFOPool 对象池

2013年02月20日 ⁄ 综合 ⁄ 共 4558字 ⁄ 字号 评论关闭
代码

public class LIFOPool<T> : IPool<T>, IFreeness where T : class
{
#region NestedTypes
internal struct LIFOEntry
{
public bool Idle;
public DateTime LastUpdate;
public T Value;
}
#endregion

#region StaticMembers
public const int DefaultMaxSize = 100;
public const int DefaultMinSize = 2;
public static readonly bool IsSubOfIDisposable;

static LIFOPool()
{
IsSubOfIDisposable
= typeof(T).IsSubclassOf(typeof(IDisposable));
}
#endregion

#region Fields
private WeakEvent<EventHandler> eventFull;
private LookupItem<T> lookupItem;
private ReleaseItem<T> releaseItem;
private double 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
<WeakEvent<EventHandler>>(ref eventFull, new WeakEvent<EventHandler>(), null);
}
eventFull.Add(value);
}
remove
{
if (eventFull != null)
{
eventFull.Remove(value);
}
}
}
public double LifeTime
{
set { Interlocked.Exchange(ref lifeTime, value); }
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 LIFOPool(LookupItem<T> createDelegate, ReleaseItem<T> releaseDelegate)
:
this(DefaultMinSize, DefaultMaxSize, createDelegate, releaseDelegate)
{

}
public LIFOPool(int min, int max, LookupItem<T> lookupDelegate, ReleaseItem<T> releaseDelegate)
{
if (lookupDelegate ="color: #000000;">== null)
{
throw new ArgumentNullException("Lookup delegate can't be null.");
}
T t1
= lookupDelegate(), t2 = lookupDelegate();
if (object.ReferenceEquals(t1, t2))
{
throw new ArgumentException("Lookup delegate can't return the same reference object.");
}
lookupItem
= lookupDelegate;
releaseItem
= releaseDelegate;
lifeTime
= Freer.DefaultLifeTime / 2D;
minSize
= min;
maxSize
= max;
freeTimeout
= 2000;
weakHandle
= new GCHandle[maxSize / 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].LastUpdate = container[1].LastUpdate = DateTime.Now;
container[
0].Value = t1;
container[
1].Value = t2;
offset
++;
locker
= new ReaderWriterLockSlim();
}
#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].LastUpdate
= DateTime.Now;
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)
{
weakHandle[i].Target
= null;
item
= (T)weakHandle[i].Target;
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;
container[i].LastUpdate
= DateTime.Now;
}
finally
{
locker.ExitWriteLock();
}
item
= container[i].Value;
break;
}
}
if (item == null)
{
locker.EnterWriteLock();
try
{
container[offset].Idle
= false;
container[offset].LastUpdate
= DateTime.Now;
item
= container[offset++].Value = lookupItem();
}
finally
{
locker.ExitWriteLock();
}
}
}
finally
{
locker.ExitUpgradeableReadLock();
}
}
return item;
}

public int Free()
{
int freed = 0;
if (lifeTime != Timeout.Infinite && offset > minSize - 1)
{
List
<T> list = null;
if (locker.TryEnterWriteLock(freeTimeout))
{
try
{
LIFOEntry entry;
for (int i = 0; i <= offset; i++)
{
entry
= container[i];
if (entry.LastUpdate.AddSeconds(lifeTime).CompareTo(DateTime.Now) <= 0)
{
if (IsSubOfIDisposable && entry.Idle)
{
if (list == null)
{
list
= new List<T>();
}
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;
}
}
}
}
finally
{
locker.ExitWriteLock();
}
}
if (list != null)
{
list.ForEach(item
=> ((IDisposable)item).Dispose());
}
}
return freed;
}
#endregion
}

抱歉!评论已关闭.