using System; using System.Collections.Concurrent; using System.Threading; namespace BotSharp.Models.CRFLite { /// /// Represents general purpose pool that has no restrictions (e.g. grows if it's required) /// /// internal sealed class Pool { private int _totalCount; private readonly ConcurrentStack _container = new ConcurrentStack(); private readonly Func, T> _creator; private readonly Action _cleaner; /// /// Initializes a new instance of the class. /// public Pool(Func, T> creator, Action cleaner = null) { _creator = creator; _cleaner = cleaner; } /// /// Gets item from pool or creates a new item /// /// public PoolItem GetOrCreate() { T item; if (_container.TryPop(out item)) { return new PoolItem(item, _cleaner, this); } var newItem = _creator(this); if (newItem == null) { throw new ApplicationException("Unable to create new pool item"); } Interlocked.Increment(ref _totalCount); return new PoolItem(newItem, _cleaner, this); } /// /// Returns amount of free items in the bag /// public int FreeCount { get { return _container.Count; } } /// /// Returns amount items created by pool /// public int TotalCount { get { return _totalCount; } } private void Return(T item) { _container.Push(item); } /// /// Pool item that is return when pool request is processed /// /// internal struct PoolItem : IDisposable { /// /// Pooled item /// public readonly T1 Item; private readonly Pool _owner; private readonly Action _cleaner; /// /// Creates a new pool item /// /// /// /// internal PoolItem(T1 item, Action cleaner, Pool owner) { Item = item; _cleaner = cleaner; _owner = owner; } /// /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. /// public void Dispose() { _cleaner?.Invoke(Item); _owner.Return(Item); } } } }