Beispiel #1
0
        /// <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&lt;MyConnection&gt; _pool;
        ///
        ///			public MyClass()
        ///			{
        ///				_config = new PoolConfig()
        ///				{
        ///					FetchOrder = PoolFetchOrder.Fifo; // 先进先出
        ///					LoanCapacity = 10; // 同一时间内,不会有超过10个连接被借出
        ///					PoolCapacity = 0; // 池内会有无限个连接可以被使用 (不过实际不会有无限个,因为在同一时间不会有超过10个连接会被借出)
        ///					MaxUses = 0; // 无限
        ///					MaxLifespan = 60 * 5 // 5分钟后过期
        ///				};
        ///				_pool = new Pool&lt;MyConnection&gt;(
        ///
        ///				//当池中没有有效的连接被使用时,该方法会被调用
        ///				() =>
        ///				{
        ///					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&lt;MyConnection&gt; _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&lt;MyConnection&gt;(
        ///
        ///				// 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);
        }