Table of Contents

Class PartitionedBuffer<T>

Namespace
Jitter2.Unmanaged
Assembly
Jitter2.dll

Manages memory for unmanaged structs, storing them sequentially in contiguous memory blocks. Each struct can either be active or inactive.

public sealed class PartitionedBuffer<T> : IDisposable where T : unmanaged

Type Parameters

T

The unmanaged type to store. Must be at least 4 bytes in size.

Inheritance
PartitionedBuffer<T>
Implements
Inherited Members
Extension Methods

Remarks

Memory Layout Requirement: The type T must reserve its first 4 bytes (sizeof(int)) for internal bookkeeping. This memory region is used to store the stable ID that maps the data back to its JHandle<T>.

Do not modify these bytes manually. A compatible struct should look like this:

[StructLayout(LayoutKind.Sequential)]
public struct RigidBodyData
{
    private readonly int _internalIndex; // Reserved by PartitionedBuffer

    public JVector Position;
    public JQuaternion Orientation;
    // ... other fields
}

Threading: Concurrent calls to Allocate(bool, bool) may trigger a resize. Use ResizeLock to synchronize access when reading data concurrently with allocations.

Disposal: This class owns unmanaged memory and must be disposed to avoid memory leaks.

Constructors

PartitionedBuffer(int, bool)

Initializes a new instance of the class.

public PartitionedBuffer(int initialSize = 1024, bool aligned64 = false)

Parameters

initialSize int

The initial size of the contiguous memory block.

aligned64 bool

Indicates whether the memory should be aligned to 64 bytes.

Fields

ResizeLock

Reader-writer lock. Locked by a writer when a resize occurs. Resizing moves the contiguous data memory addresses. Use a reader lock to access data if concurrent calls to Allocate are made.

public ReaderWriterLock ResizeLock

Field Value

ReaderWriterLock

Properties

Active

A span for all elements marked as active.

public Span<T> Active { get; }

Property Value

Span<T>

Remarks

Do not cache: This span is invalidated when the buffer resizes.

Aligned64

Indicates whether the allocated memory is aligned to a 64-byte boundary.

public bool Aligned64 { get; }

Property Value

bool

Count

Gets the number of allocated elements in the buffer.

public int Count { get; }

Property Value

int

Elements

A span for all elements.

public Span<T> Elements { get; }

Property Value

Span<T>

Remarks

Do not cache: This span is invalidated when the buffer resizes.

Inactive

A span for all elements marked as inactive.

public Span<T> Inactive { get; }

Property Value

Span<T>

Remarks

Do not cache: This span is invalidated when the buffer resizes.

TotalBytesAllocated

Returns the total amount of unmanaged memory allocated in bytes (data + indirection pages + master page table).

public long TotalBytesAllocated { get; }

Property Value

long

Methods

Allocate(bool, bool)

Allocates an unmanaged object. Growth is dynamic.

public JHandle<T> Allocate(bool active = false, bool clear = false)

Parameters

active bool

If true, the element is added to the active partition.

clear bool

If true, the element's memory (excluding the internal ID) is zeroed.

Returns

JHandle<T>

A handle to the newly allocated element.

Remarks

Threading: This method may resize the buffer, which moves all data. Use ResizeLock when calling concurrently with data access.

Dispose()

Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.

public void Dispose()

~PartitionedBuffer()

protected ~PartitionedBuffer()

Free(JHandle<T>)

Removes the associated native structure from the buffer and invalidates the handle.

public void Free(JHandle<T> handle)

Parameters

handle JHandle<T>

The handle to free.

Remarks

Safety: After calling this method, the handle becomes invalid. Do not use the handle or any cached references to its data.

GetHandle(ref T)

Returns the handle of the object. O(1) operation.

public JHandle<T> GetHandle(ref T t)

Parameters

t T

A reference to the element in the buffer.

Returns

JHandle<T>

The handle for the element.

GetIndex(JHandle<T>)

Retrieves the target index of the handle.

public int GetIndex(JHandle<T> handle)

Parameters

handle JHandle<T>

The handle to get the index for.

Returns

int

The index of the element in the buffer.

IsActive(JHandle<T>)

Checks if the element is stored as an active element. O(1).

public bool IsActive(JHandle<T> handle)

Parameters

handle JHandle<T>

The handle to check.

Returns

bool

true if the element is active; otherwise, false.

MoveToActive(JHandle<T>)

Moves an object from inactive to active.

public void MoveToActive(JHandle<T> handle)

Parameters

handle JHandle<T>

The handle of the element to move.

MoveToInactive(JHandle<T>)

Moves an object from active to inactive.

public void MoveToInactive(JHandle<T> handle)

Parameters

handle JHandle<T>

The handle of the element to move.

Swap(int, int)

Swap two entries based on their index. Adjusts handles accordingly.

public void Swap(int i, int j)

Parameters

i int

The index of the first element.

j int

The index of the second element.