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);
}
}
}
}