Core.Buffers 1.0.36

dotnet add package Core.Buffers --version 1.0.36
                    
NuGet\Install-Package Core.Buffers -Version 1.0.36
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Core.Buffers" Version="1.0.36" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Core.Buffers" Version="1.0.36" />
                    
Directory.Packages.props
<PackageReference Include="Core.Buffers" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Core.Buffers --version 1.0.36
                    
#r "nuget: Core.Buffers, 1.0.36"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Core.Buffers@1.0.36
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Core.Buffers&version=1.0.36
                    
Install as a Cake Addin
#tool nuget:?package=Core.Buffers&version=1.0.36
                    
Install as a Cake Tool

Core.Buffers

A .NET library for efficient buffer management that provides thread-safe, modern, and fast buffer functionality currently missing in vanilla .NET.

Installation

dotnet add package Core.Buffers

Features

  • DoubleBuffer<TEntity>: A thread-safe double-buffering mechanism for unmanaged types, allowing for concurrent read and write operations.
  • DoubleBufferQueue<TEntity>: A thread-safe queue implementation built on top of a double buffer, allowing for concurrent enqueue operations while maintaining the ability to swap buffers atomically.
  • CircularBuffer<T>: A thread-safe fixed-size circular buffer implementation, where the oldest item is overwritten when the buffer is full.
  • RunningSumCircularBuffer<T>: A thread-safe specialized circular buffer that maintains a running sum of its elements for fast average calculations.

Usage

DoubleBuffer<TEntity>

The DoubleBuffer<TEntity> class provides a thread-safe double-buffering mechanism that allows for concurrent read and write operations. This is particularly useful in scenarios where you need to write to a buffer while reading from another buffer.

using Core.Buffers;
using System.Buffers;

// Create a double buffer with a size of 1024 elements * 2  ( double buffer )
using var buffer = new DoubleBuffer<int>(MemoryPool<int>.Shared, 1024);

// Write to the active buffer
for (int i = 0; i < buffer.Size; i++)
{
    buffer.Active.Span[i] = i;
}

// Swap buffers atomically and get the previous buffer as ReadOnlyMemory
ReadOnlyMemory<int> previousBuffer = buffer.Swap();

// Now you can read from the previous buffer while writing to the new active buffer
// The previousBuffer can be used directly for reading

// Write to the (next) active buffer
for (int i = 0; i < buffer.Size; i++)
{
    buffer.Active.Span[i] = i;
}

// You can also access the shadow (inactive) buffer
Console.WriteLine($"Active buffer offset: {buffer.ActiveOffset}");
Console.WriteLine($"Shadow buffer offset: {buffer.ShadowOffset}");

// Read from the shadow buffer (read-only)
for (int i = 0; i < buffer.Size; i++)
{
    Console.WriteLine(buffer.Shadow.Span[i]);
}

DoubleBufferQueue<TEntity>

The DoubleBufferQueue<TEntity> class extends the DoubleBuffer<TEntity> class to provide a thread-safe queue implementation that allows for concurrent enqueue operations while maintaining the ability to swap buffers atomically.

using Core.Buffers;
using System.Buffers;

// Create a double buffer queue with a size of 1024 elements * 2 ( double buffer )
using var queue = new DoubleBufferQueue<int>(MemoryPool<int>.Shared, 1024);

// Enqueue items to the active buffer
for (int i = 0; i < 100; i++)
{
    queue.Enqueue(i);
    // or 
    if (!queue.TryEnqueue(i)) break;
}

// Check if the queue is full
if (queue.Exhausted)
{
    Console.WriteLine("Queue is full!");
}

// Get the count of items in the active buffer
Console.WriteLine($"Items in queue: {queue.Count}");

// Swap buffers atomically and get the previous buffer as ReadOnlyMemory, with the length of the committed items
ReadOnlyMemory<int> previousBuffer = queue.Swap();

// Now you can process the items in the previous buffer
// while new items are being enqueued to the new active buffer
// The previousBuffer contains only the valid items (sliced to the count)

CircularBuffer<T>

The CircularBuffer<T> class provides a thread-safe fixed-size circular buffer implementation. When the buffer is full, adding new items overwrites the oldest items. The buffer uses MemoryPool for efficient memory management.

using Core.Buffers;
using System;
using System.Buffers;
using System.Threading.Tasks;

// Method 1: Create a circular buffer with a capacity of 5, using the shared MemoryPool
using var buffer1 = new CircularBuffer<int>(5, useMemoryPool: true);

// Method 2: Create a circular buffer with a capacity of 5, using a custom MemoryPool
using var customPool = MemoryPool<int>.Create();
using var buffer2 = new CircularBuffer<int>(customPool, 5);

// Method 3: Create a circular buffer with a capacity of 5, allocated on the heap (no pooling)
using var buffer3 = new CircularBuffer<int>(null, 5);
// or
using var buffer4 = new CircularBuffer<int>(5, useMemoryPool: false);

// Add items to the buffer
for (int i = 0; i < 10; i++)
{
    var overwritten = buffer1.Push(i);
    if (overwritten.HasValue)
    {
        Console.WriteLine($"Overwritten value: {overwritten.Value}"); // Will print values 0-4 as they get overwritten
    }
}

// Check buffer state
Console.WriteLine($"Buffer count: {buffer1.Count}");    // 5
Console.WriteLine($"Buffer capacity: {buffer1.Capacity}"); // 5
Console.WriteLine($"Buffer is empty: {buffer1.IsEmpty}"); // False

// Access items by index
for (int i = 0; i < buffer1.Count; i++)
{
    Console.WriteLine($"Item at index {i}: {buffer1[i]}");
}

// Iterate through the buffer
foreach (int item in buffer1)
{
    Console.WriteLine(item);
}

// Convert to array
int[] array = buffer1.ToArray();

// Clear the buffer
buffer1.Clear();
Console.WriteLine($"Buffer is empty: {buffer1.IsEmpty}"); // True

// Thread-safe usage example
Parallel.For(0, 1000, i =>
{
    buffer1.Push(i);
});

Console.WriteLine($"After parallel push, count: {buffer1.Count}"); // Will be 5 (or capacity)

RunningSumCircularBuffer<T>

The RunningSumCircularBuffer<T> class extends the CircularBuffer<T> class to maintain a running sum of its elements, allowing for efficient average calculations. This is useful for scenarios like calculating moving averages or other statistical operations on a sliding window of data.

using Core.Buffers;
using System;
using System.Buffers;
using System.Threading.Tasks;

// Method 1: Create a running sum circular buffer with a capacity of 5, using the shared MemoryPool
using var buffer1 = new RunningSumCircularBuffer<double>(5);

// Method 2: Create a running sum circular buffer with a capacity of 5, using a custom MemoryPool
using var customPool = MemoryPool<double>.Create();
using var buffer2 = new RunningSumCircularBuffer<double>(customPool, 5);

// Method 3: Create a running sum circular buffer with a capacity of 5, allocated on the heap (no pooling)
using var buffer3 = new RunningSumCircularBuffer<double>(null, 5);

// Add items to the buffer
buffer1.Push(10.0);
buffer1.Push(20.0);
buffer1.Push(30.0);

// Get the running sum and average
Console.WriteLine($"Running sum: {buffer1.RunningSum}"); // 60.0
Console.WriteLine($"Average: {buffer1.Average}");       // 20.0

// Add more items (will start overwriting oldest items)
buffer1.Push(40.0);
buffer1.Push(50.0);
buffer1.Push(60.0); // This will overwrite 10.0

// The running sum and average are automatically updated
Console.WriteLine($"Running sum: {buffer1.RunningSum}"); // 200.0 (20+30+40+50+60)
Console.WriteLine($"Average: {buffer1.Average}");       // 40.0

// Clear the buffer
buffer1.Clear();
Console.WriteLine($"Running sum after clear: {buffer1.RunningSum}"); // 0.0
Console.WriteLine($"Average after clear: {buffer1.Average}");       // 0.0

// Thread-safe usage example
Parallel.For(0, 1000, i =>
{
    buffer1.Push(i);
});

Console.WriteLine($"After parallel push, running sum: {buffer1.RunningSum}");
Console.WriteLine($"After parallel push, average: {buffer1.Average}");

Requirements

  • .NET 7.0, .NET 8.0, or .NET 9.0

License

This project is licensed under the MIT License - see the LICENSE file for details.

Product Compatible and additional computed target framework versions.
.NET net7.0 is compatible.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 is compatible.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 was computed.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.
  • net7.0

    • No dependencies.
  • net8.0

    • No dependencies.
  • net9.0

    • No dependencies.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.0.36 211 3/5/2025
1.0.29 199 3/5/2025