Files
stgsharp/src/Nitload.Common/HighPerformance/Memory/L4.cs
T

88 lines
2.8 KiB
C#

// -----------------------------------------------------------------------------
// file="L4"
// Project: StgSharp
// Copyright (c) Nitload.
// SPDX-License-Identifier: MIT
// -----------------------------------------------------------------------------
using Nitload.Common.HighPerformance.ProcessorAbstraction;
namespace Nitload.Common.HighPerformance.Memory
{
public sealed unsafe partial class L4 : IDisposable
{
private const nuint PageSize = 4096;
private bool _disposed;
private readonly int _bindedNuma;
private readonly nuint _baseAddress;
private SwissTable _addressMap;
private TLSF _bufferAllocator;
public L4(
int bindedNuma,
uint bufferSize = 8192 * 8192,
int align = 16,
uint maxCacheLineSize = 8192
)
{
ArgumentOutOfRangeException.ThrowIfGreaterThan(bufferSize, CacheLineMetadata.MaxBufferSize);
ArgumentOutOfRangeException.ThrowIfGreaterThan(maxCacheLineSize, CacheLineMetadata.MaxBufferSize);
_bindedNuma = bindedNuma;
nuint normalizedBufferSize = (bufferSize + (PageSize - 1)) & (~(PageSize - 1));
ByteCapacity = normalizedBufferSize;
nuint swissBufferOffset = normalizedBufferSize + TLSF.RequestedAllocation;
AllocSize = swissBufferOffset + (nuint)BufferSize;
_baseAddress = (nuint)Numa.Alloc(bindedNuma, AllocSize);
_bufferAllocator = new TLSF(bufferSize, maxCacheLineSize, (void*)_baseAddress);
_addressMap = SwissTable.Create((byte*)(_baseAddress + swissBufferOffset));
}
public nuint ByteCapacity { get; init; }
public nuint AllocSize { get; init; }
public void Dispose()
{
if (_disposed) {
return;
}
_disposed = true;
_addressMap.Dispose();
Numa.Free((void*)_baseAddress, _bindedNuma, AllocSize);
GC.SuppressFinalize(this);
}
public partial Handle Map(
AddressSource source
);
internal void Collect()
{
ObjectDisposedException.ThrowIf(_disposed, this);
_bufferAllocator.Collect();
}
internal void Free(
int handle
)
{
ObjectDisposedException.ThrowIf(_disposed, this);
_bufferAllocator.Free(handle);
}
internal bool TryAllocate(
uint size,
out int handle
)
{
ObjectDisposedException.ThrowIf(_disposed, this);
return _bufferAllocator.TryAlloc(size, out handle);
}
internal partial void Predict();
}
}