Skip to content

Commit

Permalink
Fix constructor for NativeHandle and docs in Interop.Runtime (#182)
Browse files Browse the repository at this point in the history
* Update docs for `ArenaNativeAllocator`

* Update constructor and docs for `NativeHandle`

* Update generate `helloworld-app` bindings
  • Loading branch information
lithiumtoast authored Feb 20, 2025
1 parent 157b894 commit 622a166
Show file tree
Hide file tree
Showing 5 changed files with 119 additions and 15 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// <auto-generated>
// This code was generated by the following tool on 2025-01-27 02:11:24 GMT-05:00:
// This code was generated by the following tool on 2025-02-19 20:34:32 GMT-05:00:
// https://github.com/bottlenoselabs/c2cs (v0.0.0.0)
//
// Changes to this file may cause incorrect behavior and will be lost if the code is regenerated.
Expand Down
112 changes: 106 additions & 6 deletions src/cs/examples/helloworld/helloworld-app/Generated/Runtime.g.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// <auto-generated>
// This code was generated by the following tool on 2025-01-27 02:11:24 GMT-05:00:
// This code was generated by the following tool on 2025-02-19 20:34:32 GMT-05:00:
// https://github.com/bottlenoselabs/c2cs (v0.0.0.0)
//
// Changes to this file may cause incorrect behavior and will be lost if the code is regenerated.
Expand All @@ -11,6 +11,7 @@
using System;
using System.Globalization;
using System.Runtime.InteropServices;
using System.Threading;

namespace Interop.Runtime;

Expand Down Expand Up @@ -578,11 +579,11 @@ public static CString AllocateCString(this INativeAllocator allocator, string st
/// An allocator that uses a single block of native memory which can be re-used.
/// </summary>
/// <remarks>
/// <p>
/// <para>
/// The <see cref="ArenaNativeAllocator" /> can be useful in native interoperability situations when you need to
/// temporarily allocate memory. For example, when calling native functions sometimes memory needs be available
/// for one or more calls but is no longer used after.
/// </p>
/// </para>
/// </remarks>
public sealed unsafe class ArenaNativeAllocator
: INativeAllocator, IDisposable
Expand Down Expand Up @@ -614,9 +615,10 @@ public ArenaNativeAllocator(int capacity)

#if NET6_0_OR_GREATER
// malloc
_buffer = (IntPtr)NativeMemory.Alloc((UIntPtr)capacity);
_buffer = (IntPtr)NativeMemory.AllocZeroed((UIntPtr)capacity);
#else
_buffer = Marshal.AllocHGlobal(capacity);
new Span<byte>((void*)_buffer, Capacity).Clear();
#endif
Capacity = capacity;
}
Expand Down Expand Up @@ -673,14 +675,112 @@ public void Free(IntPtr pointer)
/// Resets <see cref="Used" /> to zero and clears the entire underlying block of native memory with zeroes.
/// </summary>
/// <remarks>
/// <p>
/// <para>
/// Any pointers returned from <see cref="Allocate" /> before calling <see cref="Reset" /> must not be used or else
/// there is a risk that the pointers point to unexpected bytes of data.
/// </p>
/// </para>
/// </remarks>
public void Reset()
{
#if NET6_0_OR_GREATER
NativeMemory.Clear((void*)_buffer, (UIntPtr)Used);
#else
new Span<byte>((void*)_buffer, Used).Clear();
#endif
Used = 0;
}
}

/// <summary>
/// Represents a object instance that has unmanaged resources that can be free-ed, released, or reset.
/// </summary>
public abstract class Disposable : IDisposable
{
private volatile int _isDisposed;

/// <summary>
/// Gets a value indicating whether the object instance has free-ed, released, or reset unmanaged resources.
/// </summary>
/// <remarks><para><see cref="IsDisposed" /> is thread-safe via atomic operations.</para></remarks>
public bool IsDisposed => _isDisposed == 1;

/// <summary>
/// Performs tasks related to freeing, releasing, or resetting unmanaged resources.
/// </summary>
#pragma warning disable CA1063
public void Dispose()
#pragma warning restore CA1063
{
#pragma warning disable CS0420 // A reference to a volatile field will not be treated as volatile
var isDisposed = Interlocked.CompareExchange(ref _isDisposed, 1, 0);
#pragma warning restore CS0420 // A reference to a volatile field will not be treated as volatile
if (isDisposed == 1)
{
return;
}

Dispose(true);
GC.SuppressFinalize(this);
}

/// <summary>
/// Finalizes an instance of the <see cref="Disposable" /> class.
/// </summary>
[System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]
#pragma warning disable CA1063
~Disposable()
#pragma warning restore CA1063
{
#pragma warning disable CS0420 // A reference to a volatile field will not be treated as volatile
var isDisposed = Interlocked.CompareExchange(ref _isDisposed, 1, 0);
#pragma warning restore CS0420 // A reference to a volatile field will not be treated as volatile
if (isDisposed == 1)
{
return;
}

Dispose(false);
}

/// <summary>
/// Performs tasks related to freeing, releasing, or resetting unmanaged resources.
/// </summary>
/// <param name="isDisposing">
/// <c>true</c> if <see cref="Dispose()" /> was called explicitly. <c>false</c> if
/// <see cref="Dispose()" /> was called implicitly by the garbage collector finalizer.
/// </param>
[System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]
protected abstract void Dispose(bool isDisposing);
}

/// <summary>
/// Represents an object instance that is associated with an unmanaged handle.
/// </summary>
public abstract class NativeHandle : Disposable
{
/// <summary>
/// Gets or sets the unmanaged handle associated with the object instance.
/// </summary>
/// <remarks>
/// <para>
/// <see cref="Handle" /> is <see cref="IntPtr.Zero" /> when <see cref="Disposable.IsDisposed" /> is
/// <c>true</c>.
/// </para>
/// </remarks>
public IntPtr Handle { get; protected set; }

/// <summary>
/// Initializes a new instance of the <see cref="NativeHandle"/> class.
/// </summary>
/// <param name="handle">The native handle.</param>
protected NativeHandle(IntPtr handle)
{
Handle = handle;
}

/// <inheritdoc />
protected override void Dispose(bool isDisposing)
{
Handle = IntPtr.Zero;
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// <auto-generated>
// This code was generated by the following tool on 2025-01-27 02:11:24 GMT-05:00:
// This code was generated by the following tool on 2025-02-19 20:34:32 GMT-05:00:
// https://github.com/bottlenoselabs/c2cs (v0.0.0.0)
//
// Changes to this file may cause incorrect behavior and will be lost if the code is regenerated.
Expand Down
8 changes: 4 additions & 4 deletions src/cs/production/Interop.Runtime/ArenaNativeAllocator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,11 @@ namespace Interop.Runtime;
/// An allocator that uses a single block of native memory which can be re-used.
/// </summary>
/// <remarks>
/// <p>
/// <para>
/// The <see cref="ArenaNativeAllocator" /> can be useful in native interoperability situations when you need to
/// temporarily allocate memory. For example, when calling native functions sometimes memory needs be available
/// for one or more calls but is no longer used after.
/// </p>
/// </para>
/// </remarks>
public sealed unsafe class ArenaNativeAllocator
: INativeAllocator, IDisposable
Expand Down Expand Up @@ -106,10 +106,10 @@ public void Free(IntPtr pointer)
/// Resets <see cref="Used" /> to zero and clears the entire underlying block of native memory with zeroes.
/// </summary>
/// <remarks>
/// <p>
/// <para>
/// Any pointers returned from <see cref="Allocate" /> before calling <see cref="Reset" /> must not be used or else
/// there is a risk that the pointers point to unexpected bytes of data.
/// </p>
/// </para>
/// </remarks>
public void Reset()
{
Expand Down
10 changes: 7 additions & 3 deletions src/cs/production/Interop.Runtime/NativeHandle.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,17 +11,21 @@ namespace Interop.Runtime;
public abstract class NativeHandle : Disposable
{
/// <summary>
/// Gets the unmanaged handle associated with the object instance.
/// Gets or sets the unmanaged handle associated with the object instance.
/// </summary>
/// <remarks>
/// <para>
/// <see cref="Handle" /> is <see cref="IntPtr.Zero" /> when <see cref="Disposable.IsDisposed" /> is
/// <c>true</c>.
/// </para>
/// </remarks>
public IntPtr Handle { get; internal set; }
public IntPtr Handle { get; protected set; }

internal NativeHandle(IntPtr handle)
/// <summary>
/// Initializes a new instance of the <see cref="NativeHandle"/> class.
/// </summary>
/// <param name="handle">The native handle.</param>
protected NativeHandle(IntPtr handle)
{
Handle = handle;
}
Expand Down

0 comments on commit 622a166

Please sign in to comment.