rd-net/Lifetimes/Util/SingleThreadObjectPool.cs (58 lines of code) (raw):
using System;
using System.Collections.Generic;
using System.Threading;
using JetBrains.Diagnostics;
namespace JetBrains.Util;
public class SingleThreadObjectPool<T>
{
private readonly int myMaxCapacity;
private readonly Func<T> myFactory;
private readonly Action<T>? myClear;
private readonly Stack<T> myPool;
private readonly Thread myThread;
public SingleThreadObjectPool(Func<T> factory, Action<T>? clear) : this(int.MaxValue, factory, clear)
{
}
public SingleThreadObjectPool(int maxCapacity, Func<T> factory, Action<T>? clear)
{
myMaxCapacity = maxCapacity;
myFactory = factory;
myClear = clear;
myPool = new Stack<T>();
myThread = Thread.CurrentThread;
}
public T Rent()
{
Assertion.AssertCurrentThread(myThread);
var pool = myPool;
return pool.Count > 0 ? pool.Pop() : myFactory();
}
public RentedValueCookie<T> RentCookie() => new(this, Rent());
public void Return(T value)
{
Assertion.AssertCurrentThread(myThread);
var pool = myPool;
if (pool.Count < myMaxCapacity)
{
myClear?.Invoke(value);
pool.Push(value);
}
}
}
public sealed class SingleThreadListPool<T> : SingleThreadObjectPool<List<T>>
{
public SingleThreadListPool(int maxCapacity) : base(maxCapacity, () => new List<T>(), list => list.Clear())
{
}
}
public readonly ref struct RentedValueCookie<T>
{
private readonly SingleThreadObjectPool<T> myPool;
public T Value { get; }
public RentedValueCookie(SingleThreadObjectPool<T> pool, T value)
{
myPool = pool;
Value = value;
}
public void Dispose() => myPool.Return(Value);
}