BotSharp/BotSharp.MachineLearning/CRFLite/Pool.cs
2018-08-18 16:13:49 -05:00

98 lines
3 KiB
C#

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