[转]ObjectPool

[转]ObjectPool

 

ContractedBlock.gif ExpandedBlockStart.gif ObjectPool
 
     
// #define DISABLE_POOL
using System;
using System.Collections.Generic;
using System.Text;

namespace ObjectPool {
public interface IObjectPoolMethods : IDisposable {
/// <summary>
/// This method is used to setup an instance of
/// an object.
/// </summary>
/// <remarks>
/// Use an empty constructor in the class and
/// entirely rely on this method to setup and
/// initialize the object if the class is going
/// to be used for object pooling. Do not call this
/// method from the constructor or it will be called
/// twice and will affect performace.
/// </remarks>
/// <param name="setupParameters"></param>
void SetupObject( params object [] setupParameters);
/// <summary>
/// This event must be fired when dispose is called
/// or the Object Pool will not be able to work
/// </summary>
event EventHandler Disposing;
}

/// <summary>
/// A generic class that provide object pooling functionality
/// to classes that implement the IObjectPoolMethods interface
/// </summary>
/// <remarks>
/// As long as the lock(this) statements remain this class is thread
/// </remarks>
/// <typeparam name="T">
/// The type of the object that should be pooled
/// </typeparam>
public class ObjectPool < T > where T : IObjectPoolMethods, new () {
/// <summary>
/// The MAX_POOL does not restrict the maximum
/// number of objects in the object pool
/// instead it restricts the number of
/// disposed objects that the pool will maintain
/// a reference too and attempt to pool. This
/// number should be set based on a memory and
/// usage anaylsis based on the types of objects
/// being pooled. I have found the best results
/// by setting this number to average peak objects
/// in use at one time.
/// </summary>
/// <value> 100 </value>
private const int MAX_POOL = 2000 ;
/// <summary>
/// The static instance of the object pool. Thankfully the
/// use of generics eliminates the need for a hash for each
/// different pool type
/// </summary>
private static ObjectPool < T > me = new ObjectPool < T > ();
/// <summary>
/// Using a member for the max pool count allows different
/// types to have a different value based on usage analysis
/// </summary>
private int mMaxPool = ObjectPool < T > .MAX_POOL;
/// <summary>
/// A Linked List of the WeakReferences to the objects in the pool
/// When the count of the list goes beyond the max pool count
/// items are removed from the end of the list. The objects at the
/// end of the list are also most likely to have already been collected
/// by the garbage collector.
/// </summary>
private LinkedList < WeakReference > objectPool = new LinkedList < WeakReference > ();
/// <summary>
/// Return the singleton instance
/// </summary>
/// <returns>
/// The single instance allowed for the given type
/// </returns>
public static ObjectPool < T > GetInstance() {
return me;
}
/// <summary>
/// This method gets called on the object disposing
/// event for objects created from this object pool class.
/// If the implementing class does not fire this event on
/// dispose the object pooling will not work
/// </summary>
/// <param name="sender">
/// The class instance that is pooled
/// </param>
/// <param name="e">
/// An empty event args parameters
/// </param>
/// <exception cref="System.ArgumentException">
/// Thrown if the type of the object in the weak reference does not match
/// the type of this generic instance
/// </exception>
private void Object_Disposing( object sender, EventArgs e) {
// The lock is required here because this method may
// be called from events on different threads
lock ( this ) {
Add(
new WeakReference(sender));
}
}
/// <summary>
/// This method will add a new instance to be tracked by
/// this object pooling class. This should be a reference
/// to an object that was just disposed otherwise it makes no
/// sense and will likely cause some serious problems.
/// </summary>
/// <param name="weak">
/// WeakReference to the object that was disposed
/// </param>
/// <exception cref="System.ArgumentException">
/// Thrown if the type of the object in the weak reference does not match
/// the type of this generic instance
/// </exception>
private void Add(WeakReference weak) {
objectPool.AddFirst(weak);
if (objectPool.Count >= mMaxPool) {
objectPool.RemoveLast();
}
}
/// <summary>
/// Remove the reference from the pool. This should
/// only be called when the object in the pool
/// is being reactivated or if the weak reference has
/// been determined to be expired.
/// </summary>
/// <param name="weak">
/// A reference to remove
/// </param>
/// <exception cref="System.ArgumentException">
/// Thrown if the type of the object in the weak reference does not match
/// the type of this generic instance
/// </exception>
private void Remove(WeakReference weak) {
objectPool.Remove(weak);
}
/// <summary>
/// This method will verify that the type of the weak
/// reference is valid for this generic instance. I haven't
/// figured out a way do it automagically yet
/// </summary>
/// <exception cref="System.ArgumentException">
/// Thrown if the type of the object in the weak reference does not match
/// the type of this generic instance
/// </exception>
private void TypeCheck(WeakReference weak) {
if (weak.Target != null && weak.Target.GetType() != typeof (T)) {
throw new ArgumentException( " Target type does not match pool type " , " weak " );
}
}

/// <summary>
/// This method will return an object reference that is fully
/// setup. It will either retrieve the object from the object
/// pool if there is a disposed object available or it will
/// create a new instance.
/// </summary>
/// <param name="setupParameters">
/// The setup parameters required for the
/// IObjectPoolMethods.SetupObject method. Need to find a
/// way to check for all of the types efficiently and at
/// compile time.
/// </param>
/// <returns>
/// The reference to the object
/// </returns>
public T GetObjectFromPool( params object [] setupParameters) {
T result
= default (T);
#if DISABLE_POOL
result
= new T();
result.SetupObject(setupParameters);
return result;
#else
lock ( this ) {
WeakReference remove
= null ;
foreach (WeakReference weak in objectPool) {
object o = weak.Target;
if (o != null ) {
remove
= weak;
result
= (T)o;
GC.ReRegisterForFinalize(result);
break ;
}
}
if (remove != null ) {
objectPool.Remove(remove);
}
}
if (result == null ) {
result
= new T();
result.Disposing
+= new EventHandler(Object_Disposing);
}
result.SetupObject(setupParameters);
return result;
#endif
}


}
}

 

 

 

ContractedBlock.gif ExpandedBlockStart.gif SampleObject

posted on 2010-06-09 10:50 RockyLOMO 阅读(...) 评论(...) 编辑 收藏

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值