Table of Contents

Class NativeHandle

Namespace
Pamoja.Native.Interop
Assembly
Pamoja.Native.dll

A SafeHandle over a native pointer whose release function is supplied at construction, so the handle is always released exactly once even across finalization races.

public sealed class NativeHandle : SafeHandle, IDisposable
Inheritance
NativeHandle
Implements
Inherited Members

Remarks

The helper-math capabilities expose a family of handles that differ only in which *_free function releases them, so one handle type carrying that function serves them all.

A handle behind an object with asynchronous members is created serialized: its calls run one at a time, so a send issued while a receive is waiting runs once the receive returns, rather than reaching the native object alongside it. A call that waits its turn through UseAsync<TResult>(Func<nint, TResult>) holds no thread while it waits.

Constructors

NativeHandle(nint, Action<nint>, bool)

Wraps a non-null native pointer with the function that frees it.

public NativeHandle(nint handle, Action<nint> release, bool serialized = false)

Parameters

handle nint

The pointer returned by a native constructor.

release Action<nint>

The matching native release function.

serialized bool

Run the calls on this handle one at a time.

Properties

IsInvalid

When overridden in a derived class, gets a value indicating whether the handle value is invalid.

public override bool IsInvalid { get; }

Property Value

bool

true if the handle value is invalid; otherwise, false.

Methods

Create(nint, Action<nint>, string, bool)

Creates a wrapper, throwing when the native constructor returned null.

public static NativeHandle Create(nint handle, Action<nint> release, string what, bool serialized = false)

Parameters

handle nint

The pointer returned by a native constructor.

release Action<nint>

The matching native release function.

what string

What was being created, for the exception message.

serialized bool

Run the calls on this handle one at a time.

Returns

NativeHandle

The wrapped handle.

Exceptions

PamojaException

The native constructor returned null.

Lease()

Holds the handle open until the lease is disposed.

public NativeLease Lease()

Returns

NativeLease

The lease, whose pointer stays valid until it is disposed.

Remarks

A native call that takes a span cannot go through Use<TResult>(Func<nint, TResult>), since a lambda cannot capture one, so it leases the pointer instead: using NativeLease lease = handle.Lease();. On a serialized handle the lease holds the handle's turn as well.

Exceptions

ObjectDisposedException

The handle was already released.

LendAsync<TResult>(Func<nint, Task<TResult>>)

Lends the pointer to asynchronous work, such as a call on another handle that takes this one as an argument, holding the handle open until the work ends.

public Task<TResult> LendAsync<TResult>(Func<nint, Task<TResult>> work)

Parameters

work Func<nint, Task<TResult>>

The work to run with the pointer.

Returns

Task<TResult>

Whatever the work produced.

Type Parameters

TResult

The value the work produces.

ReleaseHandle()

When overridden in a derived class, executes the code required to free the handle.

protected override bool ReleaseHandle()

Returns

bool

true if the handle is released successfully; otherwise, in the event of a catastrophic failure, false. In this case, it generates a releaseHandleFailed Managed Debugging Assistant.

Take(string)

Hands the pointer to a native call that takes ownership of it.

public nint Take(string busy)

Parameters

busy string

The message for a handle with a call running.

Returns

nint

The pointer, which the caller now owns.

Remarks

This handle never releases the pointer afterwards. A call still running on a serialized handle is using the native object, so taking it then throws rather than giving away memory that call is still reading.

Exceptions

PamojaException

A call on this handle is still running.

Use(Action<nint>)

Runs a native call that returns nothing, holding the handle open.

public void Use(Action<nint> call)

Parameters

call Action<nint>

The native call to make.

UseAsync(Action<nint>)

Runs a native call that returns nothing on the thread pool, holding the handle open.

public Task UseAsync(Action<nint> call)

Parameters

call Action<nint>

The native call to make.

Returns

Task

A task that completes when the call has returned.

UseAsync<TResult>(Func<nint, TResult>)

Runs a native call on the thread pool, holding the handle open.

public Task<TResult> UseAsync<TResult>(Func<nint, TResult> call)

Parameters

call Func<nint, TResult>

The native call to make.

Returns

Task<TResult>

Whatever the native call returned.

Type Parameters

TResult

The value the native call returns.

Remarks

On a serialized handle the call first waits, without holding a thread, for any call already running on it.

UseTry<TValue>(NativeTry<TValue>)

Runs a native call that answers "maybe", holding the handle open, and maps its bool-plus-out-parameter shape onto a nullable value.

public TValue? UseTry<TValue>(NativeTry<TValue> call) where TValue : struct

Parameters

call NativeTry<TValue>

The native call to make.

Returns

TValue?

The value the call produced, or null when it produced none.

Type Parameters

TValue

The value the native call may produce.

Use<TResult>(Func<nint, TResult>)

Runs a native call that returns a value, holding the handle open.

public TResult Use<TResult>(Func<nint, TResult> call)

Parameters

call Func<nint, TResult>

The native call to make.

Returns

TResult

Whatever the native call returned.

Type Parameters

TResult

The value the native call returns.