using System.Runtime.CompilerServices;
using System.Threading;
using Dalamud.Game.Addon.Lifecycle.AddonArgTypes;
namespace Dalamud.Game.Addon;
/// Argument pool for Addon Lifecycle services.
[ServiceManager.EarlyLoadedService]
internal sealed class AddonLifecyclePooledArgs : IServiceType
{
private readonly AddonSetupArgs?[] addonSetupArgPool = new AddonSetupArgs?[64];
private readonly AddonFinalizeArgs?[] addonFinalizeArgPool = new AddonFinalizeArgs?[64];
private readonly AddonDrawArgs?[] addonDrawArgPool = new AddonDrawArgs?[64];
private readonly AddonUpdateArgs?[] addonUpdateArgPool = new AddonUpdateArgs?[64];
private readonly AddonRefreshArgs?[] addonRefreshArgPool = new AddonRefreshArgs?[64];
private readonly AddonRequestedUpdateArgs?[] addonRequestedUpdateArgPool = new AddonRequestedUpdateArgs?[64];
private readonly AddonReceiveEventArgs?[] addonReceiveEventArgPool = new AddonReceiveEventArgs?[64];
[ServiceManager.ServiceConstructor]
private AddonLifecyclePooledArgs()
{
}
/// Rents an instance of an argument.
/// The rented instance.
/// The returner.
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public PooledEntry Rent(out AddonSetupArgs arg) => new(out arg, this.addonSetupArgPool);
/// Rents an instance of an argument.
/// The rented instance.
/// The returner.
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public PooledEntry Rent(out AddonFinalizeArgs arg) => new(out arg, this.addonFinalizeArgPool);
/// Rents an instance of an argument.
/// The rented instance.
/// The returner.
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public PooledEntry Rent(out AddonDrawArgs arg) => new(out arg, this.addonDrawArgPool);
/// Rents an instance of an argument.
/// The rented instance.
/// The returner.
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public PooledEntry Rent(out AddonUpdateArgs arg) => new(out arg, this.addonUpdateArgPool);
/// Rents an instance of an argument.
/// The rented instance.
/// The returner.
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public PooledEntry Rent(out AddonRefreshArgs arg) => new(out arg, this.addonRefreshArgPool);
/// Rents an instance of an argument.
/// The rented instance.
/// The returner.
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public PooledEntry Rent(out AddonRequestedUpdateArgs arg) =>
new(out arg, this.addonRequestedUpdateArgPool);
/// Rents an instance of an argument.
/// The rented instance.
/// The returner.
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public PooledEntry Rent(out AddonReceiveEventArgs arg) =>
new(out arg, this.addonReceiveEventArgPool);
/// Returns the object to the pool on dispose.
/// The type.
public readonly ref struct PooledEntry
where T : AddonArgs, new()
{
private readonly Span pool;
private readonly T obj;
/// Initializes a new instance of the struct.
/// An instance of the argument.
/// The pool to rent from and return to.
public PooledEntry(out T arg, Span pool)
{
this.pool = pool;
foreach (ref var item in pool)
{
if (Interlocked.Exchange(ref item, null) is { } v)
{
this.obj = arg = v;
return;
}
}
this.obj = arg = new();
}
/// Returns the item to the pool.
public void Dispose()
{
var tmp = this.obj;
foreach (ref var item in this.pool)
{
if (Interlocked.Exchange(ref item, tmp) is not { } tmp2)
return;
tmp = tmp2;
}
}
}
}