mirror of
https://github.com/microsoft/regorus.git
synced 2026-08-05 02:16:11 +00:00
- Introduce SafeHandleWrapper with gating, short drain wait, and deferred release on last in-flight exit. - Wire Engine/Program/Rvm/CompiledPolicy to wrapper (centralized handle use, interop helper). - Add C# memory growth tests (using/finalizer paths) and extend xtask C# runner options. - Add pooled marshalling utilities, ResultHelpers, and API cleanups; update versions/changelog. Fixes #570. Closes #554 Signed-off-by: Anand Krishnamoorthi <anakrish@microsoft.com>
129 lines
4.5 KiB
C#
129 lines
4.5 KiB
C#
// Copyright (c) Microsoft Corporation.
|
|
// Licensed under the MIT License.
|
|
|
|
using System;
|
|
using Regorus.Internal;
|
|
|
|
#nullable enable
|
|
namespace Regorus
|
|
{
|
|
/// <summary>
|
|
/// Helpers for configuring and inspecting Regorus memory limits via the native allocator bridge.
|
|
/// </summary>
|
|
public static class MemoryLimits
|
|
{
|
|
/// <summary>
|
|
/// Configure the process-wide global memory limit in bytes. Pass <c>null</c> to remove the limit.
|
|
/// </summary>
|
|
/// <param name="bytes">Maximum number of bytes the allocator may reserve before signalling an error.</param>
|
|
public static void SetGlobalMemoryLimit(ulong? bytes)
|
|
{
|
|
var result = API.regorus_set_global_memory_limit(bytes ?? 0, bytes.HasValue);
|
|
EnsureSuccess(result, nameof(SetGlobalMemoryLimit));
|
|
}
|
|
|
|
/// <summary>
|
|
/// Returns the currently configured global memory limit, if any.
|
|
/// </summary>
|
|
public static ulong? GetGlobalMemoryLimit()
|
|
{
|
|
var result = API.regorus_get_global_memory_limit();
|
|
return ExtractOptionalU64(result, "Failed to get global memory limit");
|
|
}
|
|
|
|
/// <summary>
|
|
/// Forces the allocator to flush this thread's pending counters into the global aggregates.
|
|
/// </summary>
|
|
public static void FlushThreadMemoryCounters()
|
|
{
|
|
var result = API.regorus_flush_thread_memory_counters();
|
|
EnsureSuccess(result, nameof(FlushThreadMemoryCounters));
|
|
}
|
|
|
|
/// <summary>
|
|
/// Immediately checks the global memory limit and throws if the allocator reports exhaustion.
|
|
/// </summary>
|
|
public static void CheckGlobalMemoryLimit()
|
|
{
|
|
var result = API.regorus_check_global_memory_limit();
|
|
EnsureSuccess(result, nameof(CheckGlobalMemoryLimit));
|
|
}
|
|
|
|
/// <summary>
|
|
/// Override the per-thread automatic flush threshold in bytes. Pass <c>null</c> to restore the default.
|
|
/// </summary>
|
|
public static void SetThreadFlushThresholdOverride(ulong? bytes)
|
|
{
|
|
var result = API.regorus_set_thread_flush_threshold_override(bytes ?? 0, bytes.HasValue);
|
|
EnsureSuccess(result, nameof(SetThreadFlushThresholdOverride));
|
|
}
|
|
|
|
/// <summary>
|
|
/// Returns the per-thread flush threshold, if automatic flushing is enabled.
|
|
/// </summary>
|
|
public static ulong? GetThreadMemoryFlushThreshold()
|
|
{
|
|
var result = API.regorus_get_thread_memory_flush_threshold();
|
|
return ExtractOptionalU64(result, "Failed to get thread memory flush threshold");
|
|
}
|
|
|
|
private static unsafe ulong? ExtractOptionalU64(RegorusResult result, string errorContext)
|
|
{
|
|
try
|
|
{
|
|
if (result.status != RegorusStatus.Ok)
|
|
{
|
|
var message = Utf8Marshaller.FromUtf8(result.error_message) ?? $"{errorContext}: native call failed";
|
|
throw result.status.CreateException(message);
|
|
}
|
|
|
|
if (!result.bool_value)
|
|
{
|
|
return null;
|
|
}
|
|
|
|
if (result.data_type != RegorusDataType.Integer)
|
|
{
|
|
throw new InvalidOperationException(
|
|
$"{errorContext}: native call returned {result.data_type} ({(int)result.data_type}) with bool_value={result.bool_value}"
|
|
);
|
|
}
|
|
|
|
try
|
|
{
|
|
return checked((ulong)result.int_value);
|
|
}
|
|
catch (OverflowException ex)
|
|
{
|
|
throw new OverflowException($"{errorContext}: native value was out of range ({result.int_value})", ex);
|
|
}
|
|
}
|
|
finally
|
|
{
|
|
API.regorus_result_drop(result);
|
|
}
|
|
}
|
|
|
|
private static void EnsureSuccess(RegorusResult result, string operation)
|
|
{
|
|
try
|
|
{
|
|
if (result.status != RegorusStatus.Ok)
|
|
{
|
|
string? message;
|
|
unsafe
|
|
{
|
|
message = Utf8Marshaller.FromUtf8(result.error_message);
|
|
}
|
|
|
|
throw result.status.CreateException(message);
|
|
}
|
|
}
|
|
finally
|
|
{
|
|
API.regorus_result_drop(result);
|
|
}
|
|
}
|
|
}
|
|
}
|