Merge pull request #5 from mlemanczyk/codex/zmodyfikuj-klase-chunk-i-zaktualizuj-agents.md

Polish chunk API docs and style
This commit is contained in:
Marek Lemańczyk authored and GitHub committed 2025-07-13 20:50:15 +02:00
commit e9887957f9
4 files changed
+93 -32

No files matched your search

+7
View File
@@ -2,6 +2,13 @@
This repository hosts various libraries distributed as NuGet packages. Keep these links up to date so contributors and tools can easily locate them.
Only the .NET SDK **8.0** is available in the execution environment. Use this version when building or running tests.
All `*.csproj` files should enable nullable reference types with `<Nullable>enable</Nullable>`.
Indent code using four spaces or a single tab per level. Place one blank line after each closing curly brace of a code block, except when several closing braces appear sequentially. Always use braces for `if` and `else` bodies.
All tests must use **xUnit** together with **FluentAssertions**.
Implementations should be optimized for maximum performance even if that introduces some code duplication. Consider applying attributes such as `MethodImplOptions.AggressiveInlining` or faster alternatives to common operations when appropriate.
## NuGet packages
- [Recyclable.Collections](https://github.com/mlemanczyk/Recyclable.Collections)
- [Recyclable.Collections.Compatibility.List](https://github.com/mlemanczyk/Recyclable.Collections.Compatibility.List)
@@ -0,0 +1,19 @@
namespace Recyclable.Collections.Pools
{
public sealed class RecyclableArrayPoolChunk<T>
{
private static readonly T[] _empty = Array.Empty<T>();
internal static T[] Empty => _empty;
internal T[] Buffer;
internal int Index;
internal RecyclableArrayPoolChunk<T>? Previous;
internal RecyclableArrayPoolChunk<T>? Next;
public RecyclableArrayPoolChunk()
{
Buffer = _empty;
}
}
}
@@ -0,0 +1,34 @@
using Microsoft.Extensions.ObjectPool;
namespace Recyclable.Collections.Pools
{
public static class RecyclableArrayPoolChunkPool<T>
{
private static readonly ObjectPool<RecyclableArrayPoolChunk<T>> _pool =
new DefaultObjectPool<RecyclableArrayPoolChunk<T>>(new DefaultPooledObjectPolicy<RecyclableArrayPoolChunk<T>>());
public static RecyclableArrayPoolChunk<T> Rent() => _pool.Get();
public static void Return(RecyclableArrayPoolChunk<T> chunk)
{
chunk.Index = 0;
chunk.Previous = null;
chunk.Next = null;
_pool.Return(chunk);
}
public static void Dispose(RecyclableArrayPoolChunk<T> chunk, bool needsClearing)
{
var buffer = chunk.Buffer;
if (buffer.Length >= RecyclableDefaults.MinPooledArrayLength)
{
RecyclableArrayPool<T>.ReturnShared(buffer, needsClearing);
}
chunk.Buffer = RecyclableArrayPoolChunk<T>.Empty;
chunk.Index = 0;
chunk.Previous = null;
chunk.Next = null;
_pool.Return(chunk);
}
}
}
+33 -32
View File
@@ -1,6 +1,5 @@
using System.Collections;
using System.Numerics;
using Microsoft.Extensions.ObjectPool;
using System.Runtime.CompilerServices;
using Recyclable.Collections.Pools;
@@ -9,23 +8,22 @@ namespace Recyclable.Collections
internal sealed class RecyclableStack<T> : IEnumerable<T>, IDisposable
{
private static readonly bool _needsClearing = !typeof(T).IsValueType;
private static readonly ObjectPool<Chunk> _chunkPool = new DefaultObjectPool<Chunk>(new DefaultPooledObjectPolicy<Chunk>());
private sealed class Chunk
{
internal T[] Buffer = Array.Empty<T>();
internal int Index;
internal Chunk? Previous;
internal Chunk? Next;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static Chunk RentChunk(int size, Chunk? previous)
private static RecyclableArrayPoolChunk<T> RentChunk(int size, RecyclableArrayPoolChunk<T>? previous)
{
var chunk = _chunkPool.Get();
chunk.Buffer = size >= RecyclableDefaults.MinPooledArrayLength
? RecyclableArrayPool<T>.RentShared(size)
: new T[size];
var chunk = RecyclableArrayPoolChunkPool<T>.Rent();
if (chunk.Buffer.Length < size)
{
if (chunk.Buffer.Length >= RecyclableDefaults.MinPooledArrayLength)
{
RecyclableArrayPool<T>.ReturnShared(chunk.Buffer, _needsClearing);
}
chunk.Buffer = size >= RecyclableDefaults.MinPooledArrayLength
? RecyclableArrayPool<T>.RentShared(size)
: new T[size];
}
chunk.Index = 0;
chunk.Previous = previous;
chunk.Next = null;
@@ -33,22 +31,19 @@ namespace Recyclable.Collections
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static void ReturnChunk(Chunk chunk)
private static void ReturnChunk(RecyclableArrayPoolChunk<T> chunk)
{
var buffer = chunk.Buffer;
if (buffer.Length >= RecyclableDefaults.MinPooledArrayLength)
{
RecyclableArrayPool<T>.ReturnShared(buffer, _needsClearing);
}
chunk.Buffer = Array.Empty<T>();
chunk.Index = 0;
chunk.Previous = null;
chunk.Next = null;
_chunkPool.Return(chunk);
RecyclableArrayPoolChunkPool<T>.Return(chunk);
}
private Chunk _current;
private Chunk _bottom;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static void DisposeChunk(RecyclableArrayPoolChunk<T> chunk)
{
RecyclableArrayPoolChunkPool<T>.Dispose(chunk, _needsClearing);
}
private RecyclableArrayPoolChunk<T> _current;
private RecyclableArrayPoolChunk<T> _bottom;
private bool _disposed;
private long _capacity;
private long _count;
@@ -179,16 +174,22 @@ namespace Recyclable.Collections
return;
}
Clear();
ReturnChunk(_current);
var chunk = _current;
while (chunk != null)
{
var previous = chunk.Previous;
DisposeChunk(chunk);
chunk = previous;
}
_disposed = true;
GC.SuppressFinalize(this);
}
public struct Enumerator : IEnumerator<T>
{
private readonly Chunk? _start;
private Chunk? _chunk;
private readonly RecyclableArrayPoolChunk<T>? _start;
private RecyclableArrayPoolChunk<T>? _chunk;
private int _index;
private T? _current;