• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

orion-ecs / keen-eye / 20068267755

09 Dec 2025 03:08PM UTC coverage: 98.012% (-0.01%) from 98.023%
20068267755

push

github

tyevco
Suppress CS0649 warning for TestVelocity test type

TestVelocity is only used for type registration tests and is never
instantiated, so the "field never assigned" warning is expected.
Suppress with clear justification comment.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Tyler Coles <tyevco@users.noreply.github.com>

878 of 884 branches covered (99.32%)

Branch coverage included in aggregate %.

4989 of 5102 relevant lines covered (97.79%)

1.24 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

91.18
/src/KeenEyes.Core/Pooling/ComponentArrayPool.cs
1
using System.Buffers;
2
using System.Runtime.CompilerServices;
3

4
namespace KeenEyes;
5

6
/// <summary>
7
/// Provides pooled arrays for component storage, reducing garbage collection pressure.
8
/// Uses .NET's built-in ArrayPool&lt;T&gt;.Shared for efficient memory reuse.
9
/// </summary>
10
/// <typeparam name="T">The component type.</typeparam>
11
/// <remarks>
12
/// <para>
13
/// This pool is a thin wrapper around <see cref="ArrayPool{T}.Shared"/> that provides
14
/// ECS-specific functionality and tracking. It can be used independently of the
15
/// archetype system for custom storage scenarios.
16
/// </para>
17
/// <para>
18
/// Rented arrays may be larger than requested due to ArrayPool's bucketing strategy.
19
/// Always track the actual count of elements separately from the array length.
20
/// </para>
21
/// </remarks>
22
public static class ComponentArrayPool<T> where T : struct
23
{
24
    private static long totalRented;
25
    private static long totalReturned;
26

27
    /// <summary>
28
    /// Gets the total number of arrays rented from this pool.
29
    /// </summary>
30
    public static long TotalRented => Interlocked.Read(ref totalRented);
1✔
31

32
    /// <summary>
33
    /// Gets the total number of arrays returned to this pool.
34
    /// </summary>
35
    public static long TotalReturned => Interlocked.Read(ref totalReturned);
1✔
36

37
    /// <summary>
38
    /// Gets the number of arrays currently rented (not returned).
39
    /// </summary>
40
    public static long OutstandingCount => TotalRented - TotalReturned;
1✔
41

42
    /// <summary>
43
    /// Rents an array of at least the specified minimum length.
44
    /// </summary>
45
    /// <param name="minimumLength">The minimum required length.</param>
46
    /// <returns>An array of at least the specified length.</returns>
47
    /// <remarks>
48
    /// The returned array may be longer than requested. Track the actual
49
    /// element count separately. When done, return the array using
50
    /// <see cref="Return(T[], bool)"/>.
51
    /// </remarks>
52
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
53
    public static T[] Rent(int minimumLength)
54
    {
55
        Interlocked.Increment(ref totalRented);
1✔
56
        return ArrayPool<T>.Shared.Rent(minimumLength);
1✔
57
    }
58

59
    /// <summary>
60
    /// Returns an array to the pool.
61
    /// </summary>
62
    /// <param name="array">The array to return.</param>
63
    /// <param name="clearArray">Whether to clear the array contents before returning.</param>
64
    /// <remarks>
65
    /// <para>
66
    /// It is recommended to set <paramref name="clearArray"/> to true for
67
    /// reference types or when arrays may contain sensitive data.
68
    /// </para>
69
    /// <para>
70
    /// After calling this method, the caller should not access the array again.
71
    /// </para>
72
    /// </remarks>
73
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
74
    public static void Return(T[] array, bool clearArray = false)
75
    {
76
        ArrayPool<T>.Shared.Return(array, clearArray);
1✔
77
        Interlocked.Increment(ref totalReturned);
1✔
78
    }
1✔
79
}
80

81
/// <summary>
82
/// Non-generic helper for ComponentArrayPool operations.
83
/// Provides AOT-compatible access for dynamic component types using explicit registration.
84
/// </summary>
85
/// <remarks>
86
/// <para>
87
/// This class uses explicit delegate registration to avoid reflection, making it compatible with
88
/// Native AOT compilation. Component types must be registered via <see cref="Register{T}"/>
89
/// before using the non-generic Rent/Return methods.
90
/// </para>
91
/// <para>
92
/// For AOT scenarios, call <see cref="Register{T}"/> during startup for all component types
93
/// that will be used dynamically. Generic <see cref="ComponentArrayPool{T}"/> can be used
94
/// directly without registration.
95
/// </para>
96
/// </remarks>
97
public static class ComponentArrayPool
98
{
99
    private delegate Array RentDelegate(int minimumLength);
100
    private delegate void ReturnDelegate(Array array, bool clearArray);
101

102
    private static readonly Dictionary<Type, RentDelegate> rentDelegates = [];
1✔
103
    private static readonly Dictionary<Type, ReturnDelegate> returnDelegates = [];
1✔
104
    private static readonly object lockObj = new();
1✔
105

106
    /// <summary>
107
    /// Registers a component type for non-generic pool access.
108
    /// </summary>
109
    /// <typeparam name="T">The component type to register.</typeparam>
110
    /// <remarks>
111
    /// This method should be called during initialization for all component types that will
112
    /// be accessed via the non-generic <see cref="Rent"/> and <see cref="Return"/> methods.
113
    /// This is required for AOT compatibility.
114
    /// </remarks>
115
    public static void Register<T>() where T : struct
116
    {
117
        var type = typeof(T);
1✔
118
        lock (lockObj)
1✔
119
        {
120
            if (!rentDelegates.ContainsKey(type))
1✔
121
            {
122
                rentDelegates[type] = static minLength => ComponentArrayPool<T>.Rent(minLength);
1✔
123
                returnDelegates[type] = static (array, clear) => ComponentArrayPool<T>.Return((T[])array, clear);
1✔
124
            }
125
        }
1✔
126
    }
1✔
127

128
    /// <summary>
129
    /// Rents an array for the specified component type.
130
    /// </summary>
131
    /// <param name="componentType">The component type.</param>
132
    /// <param name="minimumLength">The minimum required length.</param>
133
    /// <returns>A boxed array of the appropriate type.</returns>
134
    /// <exception cref="InvalidOperationException">
135
    /// Thrown when the component type has not been registered via <see cref="Register{T}"/>.
136
    /// </exception>
137
    /// <remarks>
138
    /// For AOT compatibility, the component type must be registered via <see cref="Register{T}"/>
139
    /// before calling this method. For known types at compile time, use <see cref="ComponentArrayPool{T}.Rent"/>
140
    /// directly instead.
141
    /// </remarks>
142
    public static Array Rent(Type componentType, int minimumLength)
143
    {
144
        if (!rentDelegates.TryGetValue(componentType, out var rentDelegate))
1✔
145
        {
146
            throw new InvalidOperationException(
1✔
147
                $"Component type {componentType.Name} has not been registered with ComponentArrayPool. " +
1✔
148
                $"Call ComponentArrayPool.Register<{componentType.Name}>() before using non-generic Rent/Return methods.");
1✔
149
        }
150

151
        return rentDelegate(minimumLength);
1✔
152
    }
153

154
    /// <summary>
155
    /// Returns an array to the pool for the specified component type.
156
    /// </summary>
157
    /// <param name="componentType">The component type.</param>
158
    /// <param name="array">The array to return.</param>
159
    /// <param name="clearArray">Whether to clear the array contents.</param>
160
    /// <exception cref="InvalidOperationException">
161
    /// Thrown when the component type has not been registered via <see cref="Register{T}"/>.
162
    /// </exception>
163
    /// <remarks>
164
    /// For AOT compatibility, the component type must be registered via <see cref="Register{T}"/>
165
    /// before calling this method. For known types at compile time, use <see cref="ComponentArrayPool{T}.Return"/>
166
    /// directly instead.
167
    /// </remarks>
168
    public static void Return(Type componentType, Array array, bool clearArray = false)
169
    {
170
        if (!returnDelegates.TryGetValue(componentType, out var returnDelegate))
1✔
171
        {
172
            throw new InvalidOperationException(
×
173
                $"Component type {componentType.Name} has not been registered with ComponentArrayPool. " +
×
174
                $"Call ComponentArrayPool.Register<{componentType.Name}>() before using non-generic Rent/Return methods.");
×
175
        }
176

177
        returnDelegate(array, clearArray);
1✔
178
    }
1✔
179
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc