HowTo - Pool Support

Pool unit tests can be found in System.Extensions.Tests > Pool > PoolTests_v*.cs files

namespace System.Extensions.Tests.PoolTests_v2
{
    using System;
    using System.Collections.Generic;
    using System.Diagnostics;
    using System.Threading;
    
    using Microsoft.VisualStudio.TestTools.UnitTesting;
    
    interface IConnector : IDisposable
    {
        void Send();
    }
    
    #region [ v2 -> Connector implements IPoolableObject ]
    
    class Connector : IConnector, IPoolableObject
    {
        private static int _count = 0; // used to generate Id value
    
        public Connector()
        {
            this.Id = Interlocked.Increment(ref _count); // generates the ID
        }
    
        ~Connector()
        {
            this.Dispose(false);
        }
    
        #region [ Properties ]
    
        public int Id { get; private set; }
    
        #endregion
    
        #region [ IConnector Implementation ]
    
        public void Send()
        {
            Debug.WriteLine("Connector.Send() -> #{0}", this.Id);
        }
    
        #endregion
    
        #region [ IPoolableObject Implementation ]
    
        public void Initialize(object parameter)
        {
            // add code to initialize the instance...
    
            Thread.Sleep(1000); // simulates long initialization...
    
            Debug.WriteLine("Connector_v1.Initialize() -> #{0}", this.Id);
        }
    
        public void ResetState()
        {
            // add code to reset the state of the instance...
    
            Debug.WriteLine("Connector_v1.Reset() -> #{0}", this.Id);
        }
    
        #endregion
    
        #region [ IDisposable Implementation ]
    
        private bool _isDisposed = false;
    
        public void Dispose()
        {
            this.Dispose(true);
            GC.SuppressFinalize(this);
        }
    
        protected virtual void Dispose(bool disposing)
        {
            if (disposing)
            {
                if (!_isDisposed)
                {
                    _isDisposed = true;
    
                    Debug.WriteLine("Connector.Dispose() -> #{0}", this.Id);
                }
            }
        }
    
        #endregion
    }
    
    // -> Connector implements IPoolableObject
    // -> Initialize() and ResetState() don't have to be overrided
    
    class PooledConnector : PooledObject<IConnector, Connector>, IConnector
    {
        public PooledConnector(Pool<IConnector> pool)
            : base(pool)
        {
        }
    
        #region [ IConnector Implementation ]
    
        public void Send()
        {
            _innerObject.Send();
        }
    
        #endregion
    }
    
    #endregion
    
    class ConnectorConfiguration { } // for the sample (for example to pass configuration for the pooled connectors)
    
    class ConnectorPoolManager : Singleton<ConnectorPoolManager> // if you want to use a singleton
    {
        private static readonly Pool<IConnector> _pool = new Pool<IConnector>(
            2,
            p => new PooledConnector(p),
            PoolLoadingModeEnum.Lazy, // recommended
            PoolAccessModeEnum.Circular,			
            () => { return _config; });
    
        public IConnector Acquire()
        {
            return _pool.Acquire();
        }
    }
    
    [TestClass]
    public class PoolTests
    {
        private readonly ConnectorConfiguration _config = new ConnectorConfiguration(); // for the sample
    
        [TestMethod]
        public void Extensions_PoolTest_v2_Instance_EagerCircular()
        {
            var pool = new Pool<IConnector>( // Eager -> 2 Connectors immediately created when the pool is instanciated (2 x 1000ms)
                2,
                p => new PooledConnector(p),
                PoolLoadingModeEnum.Eager,
                PoolAccessModeEnum.Circular,
                () => { return _config; });
    
            // Now the pool contains 2 Connectors
    
            using (var connector = pool.Acquire()) // -> gets Connector #1 from the pool
            {
                connector.Send();
            }
    
            // Connector #1 is released at the end of the using() and becomes available
    
            using (var connector = pool.Acquire()) // -> gets Connector #2 from the pool
            {
                connector.Send();
            }
    
            using (var connector = pool.Acquire()) // -> gets Connector #1 from the pool
            {
                connector.Send();
            }
    
            // -> the pool contains 2 Connectors
        }
    
        [TestMethod]
        public void Extensions_PoolTest_v2_Instance_LazyCircular()
        {
            var pool = new Pool<IConnector>( // -> Lazy -> no Connectors created
                2,
                p => new PooledConnector(p),
                PoolLoadingModeEnum.Lazy,
                PoolAccessModeEnum.Circular,			
                () => { return _config; });
    
            // Now the pool contains 0 Connector
    
            using (var connector = pool.Acquire()) // creates Connector #1 in the pool (1 x 1000ms)
            {
                connector.Send();
            }
    
            using (var connector = pool.Acquire()) // Connector #1 is free -> gets Connector #1 from the pool
            {
                connector.Send();
            }
    
            // -> the pool contains 1 Connector
        }
    
        [TestMethod]
        public void Extensions_PoolTest_v2_Instance_LazyExpandingCircular()
        {
            var pool = new Pool<IConnector>( // -> LazyExpanding -> no Connectors created
                2,
                p => new PooledConnector(p),
                PoolLoadingModeEnum.LazyExpanding,
                PoolAccessModeEnum.Circular,			
                () => { return _config; });
    
            // Now the pool contains 0 Connector
    
            using (var connector = pool.Acquire()) // the pool is not full -> creates Connector #1 in the pool (1 x 1000ms)
            {
                connector.Send();
            }
    
            using (var connector = pool.Acquire()) // the pool is not full -> creates Connector #2 in the pool (1 x 1000ms)
            {
                connector.Send();
            }
    
            using (var connector = pool.Acquire()) // the pool is full - the Connector #1 is free -> gets Connector #1 from the pool
            {
                connector.Send();
            }
    
            // -> the pool contains 2 Connectors
        }
    
        [TestMethod]
        public void Extensions_PoolTest_v2_Singleton()
        {
            using (var connector = ConnectorPoolManager.Current.Acquire())
            {
                connector.Send();
            }
        }
    }
}