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