mirror of
https://github.com/microsoft/regorus.git
synced 2026-08-05 02:16:11 +00:00
fix(bindings): add SafeHandleWrapper + memory growth checks; bump 0.9.1 (#571)
- 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>
This commit is contained in:
committed by
GitHub
parent
455d2aa588
commit
96360fa9d8
156
bindings/csharp/Regorus/ModuleMarshalling.cs
Normal file
156
bindings/csharp/Regorus/ModuleMarshalling.cs
Normal file
@@ -0,0 +1,156 @@
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
using System;
|
||||
using System.Buffers;
|
||||
using System.Collections.Generic;
|
||||
using Regorus;
|
||||
|
||||
#nullable enable
|
||||
|
||||
namespace Regorus.Internal
|
||||
{
|
||||
internal static unsafe class ModuleMarshalling
|
||||
{
|
||||
internal sealed class PinnedPolicyModules : IDisposable
|
||||
{
|
||||
private readonly List<Utf8Marshaller.PinnedUtf8> _pins;
|
||||
private bool _disposed;
|
||||
|
||||
internal PinnedPolicyModules(RegorusPolicyModule[] buffer, int length, List<Utf8Marshaller.PinnedUtf8> pins)
|
||||
{
|
||||
Buffer = buffer;
|
||||
Length = length;
|
||||
_pins = pins;
|
||||
}
|
||||
|
||||
internal RegorusPolicyModule[] Buffer { get; }
|
||||
|
||||
internal int Length { get; }
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if (_disposed)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (var pin in _pins)
|
||||
{
|
||||
pin.Dispose();
|
||||
}
|
||||
|
||||
ArrayPool<RegorusPolicyModule>.Shared.Return(Buffer, clearArray: true);
|
||||
_disposed = true;
|
||||
}
|
||||
}
|
||||
|
||||
internal sealed class PinnedEntryPoints : IDisposable
|
||||
{
|
||||
private readonly List<Utf8Marshaller.PinnedUtf8> _pins;
|
||||
private bool _disposed;
|
||||
|
||||
internal PinnedEntryPoints(IntPtr[] buffer, int length, List<Utf8Marshaller.PinnedUtf8> pins)
|
||||
{
|
||||
Buffer = buffer;
|
||||
Length = length;
|
||||
_pins = pins;
|
||||
}
|
||||
|
||||
internal IntPtr[] Buffer { get; }
|
||||
|
||||
internal int Length { get; }
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if (_disposed)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (var pin in _pins)
|
||||
{
|
||||
pin.Dispose();
|
||||
}
|
||||
|
||||
ArrayPool<IntPtr>.Shared.Return(Buffer, clearArray: true);
|
||||
_disposed = true;
|
||||
}
|
||||
}
|
||||
|
||||
internal static PinnedPolicyModules PinPolicyModules(IReadOnlyList<PolicyModule> modules)
|
||||
{
|
||||
if (modules is null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(modules));
|
||||
}
|
||||
|
||||
var count = modules.Count;
|
||||
var buffer = ArrayPool<RegorusPolicyModule>.Shared.Rent(count);
|
||||
var pins = new List<Utf8Marshaller.PinnedUtf8>(count * 2);
|
||||
|
||||
try
|
||||
{
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
var idPinned = Utf8Marshaller.Pin(modules[i].Id);
|
||||
var contentPinned = Utf8Marshaller.Pin(modules[i].Content);
|
||||
pins.Add(idPinned);
|
||||
pins.Add(contentPinned);
|
||||
|
||||
buffer[i] = new RegorusPolicyModule
|
||||
{
|
||||
id = idPinned.Pointer,
|
||||
content = contentPinned.Pointer
|
||||
};
|
||||
}
|
||||
|
||||
return new PinnedPolicyModules(buffer, count, pins);
|
||||
}
|
||||
catch
|
||||
{
|
||||
foreach (var pin in pins)
|
||||
{
|
||||
pin.Dispose();
|
||||
}
|
||||
|
||||
ArrayPool<RegorusPolicyModule>.Shared.Return(buffer, clearArray: true);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
internal static PinnedEntryPoints PinEntryPoints(IReadOnlyList<string> entryPoints)
|
||||
{
|
||||
if (entryPoints is null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(entryPoints));
|
||||
}
|
||||
|
||||
var count = entryPoints.Count;
|
||||
var buffer = ArrayPool<IntPtr>.Shared.Rent(count);
|
||||
var pins = new List<Utf8Marshaller.PinnedUtf8>(count);
|
||||
|
||||
try
|
||||
{
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
var entryPinned = Utf8Marshaller.Pin(entryPoints[i]);
|
||||
pins.Add(entryPinned);
|
||||
buffer[i] = (IntPtr)entryPinned.Pointer;
|
||||
}
|
||||
|
||||
return new PinnedEntryPoints(buffer, count, pins);
|
||||
}
|
||||
catch
|
||||
{
|
||||
foreach (var pin in pins)
|
||||
{
|
||||
pin.Dispose();
|
||||
}
|
||||
|
||||
ArrayPool<IntPtr>.Shared.Return(buffer, clearArray: true);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user