/// <summary> /// <para>初始化一个新的池实例</para> /// </summary> /// <param name="itemFactory"> /// <para>当池中没有可以重用的项时,用其创建一个项.</para> /// </param> /// <param name="itemFilter"> /// <para> /// 当项离开或者回到池中时,会调用这个方法。 /// 如果项可以继续重用,返回true /// 如果项需要被抛弃并从池中被移除,那么返回false /// 当项是返回池中时, phase 是 PoolItemPhase.Returning /// 当项是离开池中时,phase 是PoolItemPhase.Leaving,离开是指从池中移除,而不是借出去 /// </para> /// </param> /// <param name="config"> /// <para>池行为的配置</para> /// </param> /// <example> /// <code> /// public class MyClass /// { /// PoolConfig _config; /// Pool<MyConnection> _pool; /// /// public MyClass() /// { /// _config = new PoolConfig() /// { /// FetchOrder = PoolFetchOrder.Fifo; // 先进先出 /// LoanCapacity = 10; // 同一时间内,不会有超过10个连接被借出 /// PoolCapacity = 0; // 池内会有无限个连接可以被使用 (不过实际不会有无限个,因为在同一时间不会有超过10个连接会被借出) /// MaxUses = 0; // 无限 /// MaxLifespan = 60 * 5 // 5分钟后过期 /// }; /// _pool = new Pool<MyConnection>( /// /// //当池中没有有效的连接被使用时,该方法会被调用 /// () => /// { /// var conn = new MyConnection(); /// conn.Open(); /// return conn; /// }, /// /// //当项离开或回到池中时,该方法被调用 /// (connection, phase) => /// { /// //返回false将告诉池,该项要被抛弃 /// if(!connection.IsOpen) return false; /// /连接是返回池中时,清理连接 /// if(phase == PoolItemPhase.Returning) connection.ClearBuffer(); /// return true; /// }, /// /// _config); /// } /// /// public void SendSomeData(byte[] data) /// { /// using(var conn = _pool.Borrow()) /// { /// try /// { /// conn.Item.SendSomeDataTo("127.0.0.1", data); /// } /// catch(MyException) /// { /// //在出错的情况下,通知池,该连接返回到池中时,应该被抛弃 /// conn.IsCorrupted = true; /// throw; /// } /// } /// } /// } /// </code> /// </example> public Pool( Func <T> itemFactory, Func <T, PoolItemPhase, bool> itemFilter, Action <T> itemDestroyer, PoolConfig config) { if (itemFactory == null) { throw new ArgumentNullException("itemFactory"); } if (config == null) { throw new ArgumentNullException("config"); } _itemFactory = itemFactory; _itemFilter = itemFilter; _itemDestroyer = itemDestroyer; _loanCapacity = config.LoanCapacity; _poolCapacity = config.PoolCapacity; _maxRemainTime = config.MaxRemainTime; _maxLifespan = config.MaxLifespan; _maxUses = config.MaxUses; _fetchOrder = config.FetchOrder; _container = _createContainer(config.PoolCapacity > 0 ? config.PoolCapacity : 10); }
/// <summary> /// <para>Initializes a new instance of the <see cref="Pool{T}"/> class.</para> /// </summary> /// <param name="itemFactory"> /// <para>Builds new items when no re-usable items are available in the pool.</para> /// </param> /// <param name="itemFilter"> /// <para>Called when items leave and return to the pool. Should return /// <see langword="true"/> if the item is re-usable and <see langword="false"/> if the item should /// be disposed and removed from the pool. If the item needs to be reset /// it should be done in this method when the phase is <see cref="PoolItemPhase.Returning"/> /// or <see cref="PoolItemPhase.Leaving"/>.</para> /// </param> /// <param name="config"> /// <para>Configuration settings that dictate the behavior of the pool.</para> /// </param> /// <exception cref="ArgumentNullException"> /// <para><paramref name="itemFactory"/> is <see langword="null"/>.</para> /// <para>- or -</para> /// <para><paramref name="config"/> is <see langword="null"/>.</para> /// </exception> /// <exception cref="NotSupportedException"> /// <para><paramref name="config.FetchOrder"/> is not supported; /// supported types are <see cref="PoolFetchOrder.Fifo"/> and /// <see cref="PoolFetchOrder.Lifo"/>.</para> /// </exception> /// <example> /// <code> /// public class MyClass /// { /// PoolConfig _config; /// Pool<MyConnection> _pool; /// /// public MyClass() /// { /// _config = new PoolConfig() /// { /// FetchOrder = PoolFetchOrder.Fifo; // queue-like /// LoanCapacity = 10; // no more than 10 items in use simultaneously /// PoolCapacity = 0; // pool can hold any number of connections (but won't /// // because no more than 10 can be borrowed at a time) /// MaxUses = 0; // unlimited /// MaxLifespan = 60 * 5 // expire after 5 minutes /// }; /// _pool = new Pool<MyConnection>( /// /// // Called when no existing connections are available in the pool. /// () => /// { /// var conn = new MyConnection(); /// conn.Open(); /// return conn; /// }, /// /// // Called when items leave and return to the pool. /// (connection, phase) => /// { /// // Returning false will tell the pool to discard the item. /// if(!connection.IsOpen) return false; /// // Only clear when connections are returned to the pool. /// if(phase == PoolItemPhase.Returning) connection.ClearBuffer(); /// return true; /// }, /// /// _config); /// } /// /// public void SendSomeData(byte[] data) /// { /// using(var conn = _pool.Borrow()) /// { /// try /// { /// conn.Item.SendSomeDataTo("127.0.0.1", data); /// } /// catch(MyException) /// { /// // Setting this to true will tell the pool to discard /// // the item when it is returned to the pool. /// conn.IsCorrupted = true; /// throw; /// } /// } /// } /// } /// </code> /// </example> public Pool( Factory <T> itemFactory, Factory <T, PoolItemPhase, bool> itemFilter, PoolConfig config) { if (itemFactory == null) { throw new ArgumentNullException("itemFactory"); } if (config == null) { throw new ArgumentNullException("config"); } _itemFactory = itemFactory; _itemFilter = itemFilter; _loanCapacity = config.LoanCapacity; _poolCapacity = config.PoolCapacity; _maxLifespan = config.MaxLifespan; _maxUses = config.MaxUses; _finalizeLeaks = _loanCapacity > 0 && config.FinalizeLeaks; _fetchOrder = config.FetchOrder; _container = _createContainer(config.PoolCapacity > 0 ? config.PoolCapacity : 10); }