aboutsummaryrefslogtreecommitdiff
path: root/lib/Utils
diff options
context:
space:
mode:
authorLibravatar vnugent <public@vaughnnugent.com>2024-03-31 17:00:45 -0400
committerLibravatar vnugent <public@vaughnnugent.com>2024-03-31 17:00:45 -0400
commit21130c889bd8564b201aa16c8f645abdf85d374a (patch)
tree57e685f0f7e5c341264eb890112de35206f3d289 /lib/Utils
parent55859158fbd0bf54473a0baeb486045a025c7c5d (diff)
Squashed commit of the following:
commit 448a93bb1d18d032087afe2476ffccb98634a54c Author: vnugent <public@vaughnnugent.com> Date: Sun Mar 31 16:56:51 2024 -0400 ci: fix third-party dir cleanup commit 9afed1427472da1ea13079f98dbe27339e55ee7d Author: vnugent <public@vaughnnugent.com> Date: Sun Mar 31 16:43:15 2024 -0400 perf: Deprecate unsafememoryhandle span extensions commit 3ff90da4f02af47ea6d233fdd4445337ebe36452 Author: vnugent <public@vaughnnugent.com> Date: Sat Mar 30 21:36:18 2024 -0400 refactor: Updates, advanced tracing, http optimizations commit 8d6b79b5ae309b36f265ba81529bcef8bfcd7414 Merge: 6c1667b 5585915 Author: vnugent <public@vaughnnugent.com> Date: Sun Mar 24 21:01:31 2024 -0400 Merge branch 'main' into develop commit 6c1667be23597513537f8190e2f55d65eb9b7c7a Author: vnugent <public@vaughnnugent.com> Date: Fri Mar 22 12:01:53 2024 -0400 refactor: Overhauled native library loading and lazy init commit ebf688f2f974295beabf7b5def7e6f6f150551d0 Author: vnugent <public@vaughnnugent.com> Date: Wed Mar 20 22:16:17 2024 -0400 refactor: Update compression header files and macros + Ci build commit 9c7b564911080ccd5cbbb9851a0757b05e1e9047 Author: vnugent <public@vaughnnugent.com> Date: Tue Mar 19 21:54:49 2024 -0400 refactor: JWK overhaul & add length getter to FileUpload commit 6d8c3444e09561e5957491b3cc1ae858e0abdd14 Author: vnugent <public@vaughnnugent.com> Date: Mon Mar 18 16:13:20 2024 -0400 feat: Add FNV1a software checksum and basic correction tests commit 00d182088cecefc08ca80b1faee9bed3f215f40b Author: vnugent <public@vaughnnugent.com> Date: Fri Mar 15 01:05:27 2024 -0400 chore: #6 Use utils filewatcher instead of built-in commit d513c10d9895c6693519ef1d459c6a5a76929436 Author: vnugent <public@vaughnnugent.com> Date: Sun Mar 10 21:58:14 2024 -0400 source tree project location updated
Diffstat (limited to 'lib/Utils')
-rw-r--r--lib/Utils/src/AdvancedTrace.cs52
-rw-r--r--lib/Utils/src/Async/AsyncAccessSerializer.cs43
-rw-r--r--lib/Utils/src/Async/AsyncQueue.cs12
-rw-r--r--lib/Utils/src/Extensions/MemoryExtensions.cs52
-rw-r--r--lib/Utils/src/Memory/IMemoryHandle.cs4
-rw-r--r--lib/Utils/src/Memory/MemoryHandle.cs15
-rw-r--r--lib/Utils/src/Memory/MemoryUtil.cs45
-rw-r--r--lib/Utils/src/Memory/UnsafeMemoryHandle.cs34
-rw-r--r--lib/Utils/src/Native/SafeLibraryHandle.cs11
-rw-r--r--lib/Utils/src/Resources/CallbackOpenHandle.cs44
-rw-r--r--lib/Utils/src/Resources/ManagedLibrary.cs22
-rw-r--r--lib/Utils/src/VNLib.Utils.csproj4
12 files changed, 196 insertions, 142 deletions
diff --git a/lib/Utils/src/AdvancedTrace.cs b/lib/Utils/src/AdvancedTrace.cs
new file mode 100644
index 0000000..0507089
--- /dev/null
+++ b/lib/Utils/src/AdvancedTrace.cs
@@ -0,0 +1,52 @@
+/*
+* Copyright (c) 2024 Vaughn Nugent
+*
+* Library: VNLib
+* Package: VNLib.Utils
+* File: AdvancedTrace.cs
+*
+* AdvancedTrace.cs is part of VNLib.Utils which is part of the larger
+* VNLib collection of libraries and utilities.
+*
+* VNLib.Utils is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published
+* by the Free Software Foundation, either version 2 of the License,
+* or (at your option) any later version.
+*
+* VNLib.Utils is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with VNLib.Utils. If not, see http://www.gnu.org/licenses/.
+*/
+
+using System.Diagnostics;
+
+namespace VNLib.Utils
+{
+ /// <summary>
+ /// Provides methods for advanced tracing that are only optionally compiled
+ /// with the VNLIB_ADVANCED_TRACING symbol defined
+ /// </summary>
+ internal static class AdvancedTrace
+ {
+ const string AdvancedTraceSymbol = "VNLIB_ADVANCED_TRACING";
+
+ [Conditional(AdvancedTraceSymbol)]
+ public static void WriteLine(string? message) => Trace.WriteLine(message);
+
+ [Conditional(AdvancedTraceSymbol)]
+ public static void WriteLine(string? message, string? category) => Trace.WriteLine(message, category);
+
+ [Conditional(AdvancedTraceSymbol)]
+ public static void WriteLineIf(bool condition, string? message) => Trace.WriteLineIf(condition, message);
+
+ [Conditional(AdvancedTraceSymbol)]
+ public static void WriteLineIf(bool condition, string? message, string? category) => Trace.WriteLineIf(condition, message, category);
+
+ [Conditional(AdvancedTraceSymbol)]
+ public static void WriteLine(object? value) => Trace.WriteLine(value);
+ }
+} \ No newline at end of file
diff --git a/lib/Utils/src/Async/AsyncAccessSerializer.cs b/lib/Utils/src/Async/AsyncAccessSerializer.cs
index 76532bc..1beb4dc 100644
--- a/lib/Utils/src/Async/AsyncAccessSerializer.cs
+++ b/lib/Utils/src/Async/AsyncAccessSerializer.cs
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2023 Vaughn Nugent
+* Copyright (c) 2024 Vaughn Nugent
*
* Library: VNLib
* Package: VNLib.Utils
@@ -37,42 +37,35 @@ namespace VNLib.Utils.Async
/// Creates a base concrete implementation of an <see cref="IAsyncAccessSerializer{TMoniker}"/>
/// </summary>
/// <typeparam name="TMoniker">The moniker (key) type</typeparam>
- public class AsyncAccessSerializer<TMoniker> : IAsyncAccessSerializer<TMoniker>, ICacheHolder where TMoniker : notnull
+ /// <remarks>
+ /// Initializes a new <see cref="AsyncAccessSerializer{TMoniker}"/> with the desired
+ /// caching pool size and initial capacity
+ /// </remarks>
+ /// <param name="maxPoolSize">The maxium number of cached wait entry objects</param>
+ /// <param name="initialCapacity">The initial capacity of the wait table</param>
+ /// <param name="keyComparer">The moniker key comparer</param>
+ public class AsyncAccessSerializer<TMoniker>(int maxPoolSize, int initialCapacity, IEqualityComparer<TMoniker>? keyComparer)
+ : IAsyncAccessSerializer<TMoniker>, ICacheHolder where TMoniker : notnull
{
/// <summary>
/// The mutual exclusion monitor locking object
/// </summary>
- protected object StoreLock { get; }
+ protected object StoreLock { get; } = new();
/// <summary>
/// A cache pool for <see cref="WaitEntry"/>
/// </summary>
- protected Stack<WaitEntry> EntryPool { get; }
+ protected Stack<WaitEntry> EntryPool { get; } = new(maxPoolSize);
/// <summary>
/// The table containing all active waiters
/// </summary>
- protected Dictionary<TMoniker, WaitEntry> WaitTable { get; }
+ protected Dictionary<TMoniker, WaitEntry> WaitTable { get; } = new(initialCapacity, keyComparer);
/// <summary>
/// The maxium number of elements allowed in the internal entry cache pool
/// </summary>
- protected int MaxPoolSize { get; }
-
- /// <summary>
- /// Initializes a new <see cref="AsyncAccessSerializer{TMoniker}"/> with the desired
- /// caching pool size and initial capacity
- /// </summary>
- /// <param name="maxPoolSize">The maxium number of cached wait entry objects</param>
- /// <param name="initialCapacity">The initial capacity of the wait table</param>
- /// <param name="keyComparer">The moniker key comparer</param>
- public AsyncAccessSerializer(int maxPoolSize, int initialCapacity, IEqualityComparer<TMoniker>? keyComparer)
- {
- MaxPoolSize = maxPoolSize;
- StoreLock = new();
- EntryPool = new(maxPoolSize);
- WaitTable = new(initialCapacity, keyComparer);
- }
+ protected int MaxPoolSize { get; } = maxPoolSize;
///<inheritdoc/>
public virtual Task WaitAsync(TMoniker moniker, CancellationToken cancellation = default)
@@ -464,11 +457,9 @@ namespace VNLib.Utils.Async
* next task in the queue and be awaitable as a task
*/
- private sealed class TaskNode : Task
+ private sealed class TaskNode(Action<object?> callback, object item, CancellationToken cancellation)
+ : Task(callback, item, cancellation)
{
- public TaskNode(Action<object?> callback, object item, CancellationToken cancellation) : base(callback, item, cancellation)
- { }
-
public TaskNode? Next { get; set; }
}
@@ -500,7 +491,7 @@ namespace VNLib.Utils.Async
/// another waiter is not selected.
/// </para>
/// </summary>
- /// <returns>A value that indicates if the task was transition successfully</returns>
+ /// <returns>A value that indicates if the task was transitioned successfully</returns>
public readonly bool Release()
{
//return success if no next waiter
diff --git a/lib/Utils/src/Async/AsyncQueue.cs b/lib/Utils/src/Async/AsyncQueue.cs
index 45f1219..e94d08e 100644
--- a/lib/Utils/src/Async/AsyncQueue.cs
+++ b/lib/Utils/src/Async/AsyncQueue.cs
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2023 Vaughn Nugent
+* Copyright (c) 2024 Vaughn Nugent
*
* Library: VNLib
* Package: VNLib.Utils
@@ -93,19 +93,13 @@ namespace VNLib.Utils.Async
/// Initalizes a new unbound channel based queue
/// </summary>
/// <param name="ubOptions">Channel options</param>
- public AsyncQueue(UnboundedChannelOptions ubOptions)
- {
- _channel = Channel.CreateUnbounded<T>(ubOptions);
- }
+ public AsyncQueue(UnboundedChannelOptions ubOptions) => _channel = Channel.CreateUnbounded<T>(ubOptions);
/// <summary>
/// Initalizes a new bound channel based queue
/// </summary>
/// <param name="options">Channel options</param>
- public AsyncQueue(BoundedChannelOptions options)
- {
- _channel = Channel.CreateBounded<T>(options);
- }
+ public AsyncQueue(BoundedChannelOptions options) => _channel = Channel.CreateBounded<T>(options);
/// <inheritdoc/>
public bool TryEnque(T item) => _channel.Writer.TryWrite(item);
diff --git a/lib/Utils/src/Extensions/MemoryExtensions.cs b/lib/Utils/src/Extensions/MemoryExtensions.cs
index 8f90525..65d90a0 100644
--- a/lib/Utils/src/Extensions/MemoryExtensions.cs
+++ b/lib/Utils/src/Extensions/MemoryExtensions.cs
@@ -50,6 +50,8 @@ namespace VNLib.Utils.Extensions
/// <returns>A new <see cref="OpenResourceHandle{T}"/> encapsulating the rented array</returns>
public static UnsafeMemoryHandle<T> UnsafeAlloc<T>(this ArrayPool<T> pool, int size, bool zero = false) where T : unmanaged
{
+ ArgumentNullException.ThrowIfNull(pool);
+
T[] array = pool.Rent(size);
if (zero)
@@ -268,7 +270,7 @@ namespace VNLib.Utils.Extensions
/// <summary>
/// Gets a reference to the element at the specified offset from the base
- /// address of the <see cref="MemoryHandle{T}"/>
+ /// address of the <see cref="IMemoryHandle{T}"/>
/// </summary>
/// <param name="block"></param>
/// <param name="offset">The element offset from the base address to add to the returned reference</param>
@@ -766,52 +768,6 @@ namespace VNLib.Utils.Extensions
#endregion
/// <summary>
- /// Slices the current array by the specified starting offset to the end
- /// of the array
- /// </summary>
- /// <typeparam name="T">The array type</typeparam>
- /// <param name="arr"></param>
- /// <param name="start">The start offset of the new array slice</param>
- /// <returns>The sliced array</returns>
- /// <exception cref="ArgumentOutOfRangeException"></exception>
- public static T[] Slice<T>(this T[] arr, int start)
- {
- ArgumentNullException.ThrowIfNull(arr);
- ArgumentOutOfRangeException.ThrowIfNegative(start);
- ArgumentOutOfRangeException.ThrowIfGreaterThanOrEqual(start, arr.Length);
-
- Range sliceRange = new(start, arr.Length - start);
- return RuntimeHelpers.GetSubArray(arr, sliceRange);
- }
-
- /// <summary>
- /// Slices the current array by the specified starting offset to including the
- /// speciifed number of items
- /// </summary>
- /// <typeparam name="T">The array type</typeparam>
- /// <param name="arr"></param>
- /// <param name="start">The start offset of the new array slice</param>
- /// <param name="count">The size of the new array</param>
- /// <returns>The sliced array</returns>
- /// <exception cref="ArgumentOutOfRangeException"></exception>
- public static T[] Slice<T>(this T[] arr, int start, int count)
- {
- ArgumentNullException.ThrowIfNull(arr);
- ArgumentOutOfRangeException.ThrowIfNegative(start);
- ArgumentOutOfRangeException.ThrowIfNegative(count);
- ArgumentOutOfRangeException.ThrowIfGreaterThanOrEqual(start + count, arr.Length);
-
- if(count == 0)
- {
- return [];
- }
-
- //Calc the slice range
- Range sliceRange = new(start, start + count);
- return RuntimeHelpers.GetSubArray(arr, sliceRange);
- }
-
- /// <summary>
/// Creates a new sub-sequence over the target handle. (allows for convient sub span)
/// </summary>
/// <typeparam name="T"></typeparam>
@@ -877,6 +833,7 @@ namespace VNLib.Utils.Extensions
/// <returns>The sub-sequence of the current handle</returns>
/// <exception cref="ArgumentOutOfRangeException"></exception>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
+ [Obsolete("Functions are included directly on the type now")]
public static Span<T> AsSpan<T>(this in UnsafeMemoryHandle<T> handle, int start) where T: unmanaged => handle.Span[start..];
/// <summary>
@@ -889,6 +846,7 @@ namespace VNLib.Utils.Extensions
/// <returns>The sub-sequence of the current handle</returns>
/// <exception cref="ArgumentOutOfRangeException"></exception>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
+ [Obsolete("Functions are included directly on the type now")]
public static Span<T> AsSpan<T>(this in UnsafeMemoryHandle<T> handle, int start, int count) where T : unmanaged => handle.Span.Slice(start, count);
/// <summary>
diff --git a/lib/Utils/src/Memory/IMemoryHandle.cs b/lib/Utils/src/Memory/IMemoryHandle.cs
index f4e1a36..b538f87 100644
--- a/lib/Utils/src/Memory/IMemoryHandle.cs
+++ b/lib/Utils/src/Memory/IMemoryHandle.cs
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2023 Vaughn Nugent
+* Copyright (c) 2024 Vaughn Nugent
*
* Library: VNLib
* Package: VNLib.Utils
@@ -46,7 +46,7 @@ namespace VNLib.Utils.Memory
/// <summary>
/// Gets a reference to the first element in the block
/// </summary>
- /// <returns>The reference</returns>
+ /// <returns>The reference to the first element in the block</returns>
ref T GetReference();
}
diff --git a/lib/Utils/src/Memory/MemoryHandle.cs b/lib/Utils/src/Memory/MemoryHandle.cs
index c5cc295..16fc555 100644
--- a/lib/Utils/src/Memory/MemoryHandle.cs
+++ b/lib/Utils/src/Memory/MemoryHandle.cs
@@ -188,8 +188,7 @@ namespace VNLib.Utils.Memory
this.ThrowIfClosed();
//Get ptr and offset it
- T* bs = ((T*)handle) + elements;
- return bs;
+ return ((T*)handle) + elements;
}
///<inheritdoc/>
@@ -199,6 +198,16 @@ namespace VNLib.Utils.Memory
return ref MemoryUtil.GetRef<T>(handle);
}
+ /// <summary>
+ /// Gets a reference to the element at the specified offset from the base
+ /// address of the <see cref="MemoryHandle{T}"/>
+ /// </summary>
+ /// <param name="offset">The element offset from the base address to add to the returned reference</param>
+ /// <returns>The reference to the item at the desired offset</returns>
+ /// <exception cref="ArgumentOutOfRangeException"></exception>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public unsafe ref T GetOffsetRef(nuint offset) => ref Unsafe.AsRef<T>(GetOffset(offset));
+
///<inheritdoc/>
///<exception cref="ObjectDisposedException"></exception>
///<exception cref="ArgumentOutOfRangeException"></exception>
@@ -248,6 +257,6 @@ namespace VNLib.Utils.Memory
public override bool Equals(object? obj) => obj is MemoryHandle<T> oHandle && Equals(oHandle);
///<inheritdoc/>
- public override int GetHashCode() => base.GetHashCode();
+ public override int GetHashCode() => HashCode.Combine(base.GetHashCode(), handle.GetHashCode(), _length);
}
} \ No newline at end of file
diff --git a/lib/Utils/src/Memory/MemoryUtil.cs b/lib/Utils/src/Memory/MemoryUtil.cs
index b6eadbc..7ce7c81 100644
--- a/lib/Utils/src/Memory/MemoryUtil.cs
+++ b/lib/Utils/src/Memory/MemoryUtil.cs
@@ -1349,6 +1349,51 @@ namespace VNLib.Utils.Memory
public static MemoryHandle GetMemoryHandleFromPointer(IntPtr value, GCHandle handle = default, IPinnable? pinnable = null)
=> new (value.ToPointer(), handle, pinnable);
+
+ /// <summary>
+ /// Slices the current array by the specified starting offset to the end
+ /// of the array
+ /// </summary>
+ /// <typeparam name="T">The array type</typeparam>
+ /// <param name="arr"></param>
+ /// <param name="start">The start offset of the new array slice</param>
+ /// <returns>The sliced array</returns>
+ /// <exception cref="ArgumentNullException"></exception>
+ /// <exception cref="ArgumentOutOfRangeException"></exception>
+ public static T[] SliceArray<T>(T[] arr, int start)
+ {
+ ArgumentNullException.ThrowIfNull(arr);
+ return SliceArray(arr, start, arr.Length - start);
+ }
+
+ /// <summary>
+ /// Slices the current array by the specified starting offset to including the
+ /// speciifed number of items
+ /// </summary>
+ /// <typeparam name="T">The array type</typeparam>
+ /// <param name="arr"></param>
+ /// <param name="start">The start offset of the new array slice</param>
+ /// <param name="count">The size of the new array</param>
+ /// <returns>The sliced array</returns>
+ /// <exception cref="ArgumentNullException"></exception>
+ /// <exception cref="ArgumentOutOfRangeException"></exception>
+ public static T[] SliceArray<T>(T[] arr, int start, int count)
+ {
+ ArgumentNullException.ThrowIfNull(arr);
+ ArgumentOutOfRangeException.ThrowIfNegative(start);
+ ArgumentOutOfRangeException.ThrowIfNegative(count);
+ ArgumentOutOfRangeException.ThrowIfGreaterThanOrEqual(start + count, arr.Length);
+
+ if (count == 0)
+ {
+ return [];
+ }
+
+ //Calc the slice range
+ Range sliceRange = new(start, start + count);
+ return RuntimeHelpers.GetSubArray(arr, sliceRange);
+ }
+
/// <summary>
/// Gets a <see cref="Span{T}"/> from the supplied address
/// </summary>
diff --git a/lib/Utils/src/Memory/UnsafeMemoryHandle.cs b/lib/Utils/src/Memory/UnsafeMemoryHandle.cs
index fbf96eb..d93739d 100644
--- a/lib/Utils/src/Memory/UnsafeMemoryHandle.cs
+++ b/lib/Utils/src/Memory/UnsafeMemoryHandle.cs
@@ -49,8 +49,9 @@ namespace VNLib.Utils.Memory
PrivateHeap
}
- private readonly IntPtr _memoryPtr;
private readonly int _length;
+
+ private readonly IntPtr _memoryPtr;
private readonly HandleType _handleType;
private readonly T[]? _poolArr;
@@ -115,6 +116,11 @@ namespace VNLib.Utils.Memory
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal UnsafeMemoryHandle(IUnmangedHeap heap, IntPtr initial, int elements)
{
+ //Never allow non-empty handles
+ Debug.Assert(heap != null);
+ Debug.Assert(initial != IntPtr.Zero);
+ Debug.Assert(elements > 0);
+
_pool = null;
_poolArr = null;
_heap = heap;
@@ -196,6 +202,32 @@ namespace VNLib.Utils.Memory
}
}
+ /// <summary>
+ /// Returns a <see cref="Span{T}"/> that represents the memory block pointed to by this handle
+ /// </summary>
+ /// <returns>The memory block that is held by the internl handle</returns>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public readonly Span<T> AsSpan() => Span;
+
+ /// <summary>
+ /// Returns a <see cref="Span{T}"/> that represents the memory block pointed to by this handle
+ /// </summary>
+ /// <param name="start">A starting element offset to return the span at</param>
+ /// <returns>The desired memory block at the desired element offset</returns>
+ /// <exception cref="ArgumentOutOfRangeException"></exception>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public readonly Span<T> AsSpan(int start) => Span[start..];
+
+ /// <summary>
+ /// Returns a <see cref="Span{T}"/> that represents the memory block pointed to by this handle
+ /// </summary>
+ /// <param name="start">The starting element offset</param>
+ /// <param name="length">The number of elements included in the returned span</param>
+ /// <returns>The desired memory block at the desired element offset and length</returns>
+ /// <exception cref="ArgumentOutOfRangeException"></exception>"
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public readonly Span<T> AsSpan(int start, int length) => Span.Slice(start, length);
+
///<inheritdoc/>
public readonly override int GetHashCode()
{
diff --git a/lib/Utils/src/Native/SafeLibraryHandle.cs b/lib/Utils/src/Native/SafeLibraryHandle.cs
index 5fb2283..4b4ead4 100644
--- a/lib/Utils/src/Native/SafeLibraryHandle.cs
+++ b/lib/Utils/src/Native/SafeLibraryHandle.cs
@@ -63,9 +63,8 @@ namespace VNLib.Utils.Native
{
//Get the method pointer
IntPtr nativeMethod = NativeLibrary.GetExport(handle, functionName);
- //Get the delegate for the function pointer
- T method = Marshal.GetDelegateForFunctionPointer<T>(nativeMethod);
- return new(this, method);
+ AdvancedTrace.WriteLine($"Loaded function '{functionName}' with address: 0x'{nativeMethod:x}'");
+ return new(this, Marshal.GetDelegateForFunctionPointer<T>(nativeMethod));
}
catch
{
@@ -90,6 +89,7 @@ namespace VNLib.Utils.Native
this.ThrowIfClosed();
//Get the method pointer
IntPtr nativeMethod = NativeLibrary.GetExport(handle, functionName);
+ AdvancedTrace.WriteLine($"Loaded function '{functionName}' with address: 0x'{nativeMethod:x}'");
//Get the delegate for the function pointer
return Marshal.GetDelegateForFunctionPointer<T>(nativeMethod);
}
@@ -97,6 +97,7 @@ namespace VNLib.Utils.Native
///<inheritdoc/>
protected override bool ReleaseHandle()
{
+ AdvancedTrace.WriteLine($"Releasing library handle: 0x'{handle:x}'");
//Free the library and set the handle as invalid
NativeLibrary.Free(handle);
SetHandleAsInvalid();
@@ -211,7 +212,9 @@ namespace VNLib.Utils.Native
NatveLibraryResolver resolver = new(libPath, assembly, searchPath);
- return resolver.ResolveAndLoadLibrary(out library);
+ bool success = resolver.ResolveAndLoadLibrary(out library);
+ AdvancedTrace.WriteLineIf(success, $"Loaded library '{libPath}' with address: 0x'{library?.DangerousGetHandle():x}'");
+ return success;
}
}
}
diff --git a/lib/Utils/src/Resources/CallbackOpenHandle.cs b/lib/Utils/src/Resources/CallbackOpenHandle.cs
deleted file mode 100644
index 625bd45..0000000
--- a/lib/Utils/src/Resources/CallbackOpenHandle.cs
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
-* Copyright (c) 2022 Vaughn Nugent
-*
-* Library: VNLib
-* Package: VNLib.Utils
-* File: CallbackOpenHandle.cs
-*
-* CallbackOpenHandle.cs is part of VNLib.Utils which is part of the larger
-* VNLib collection of libraries and utilities.
-*
-* VNLib.Utils is free software: you can redistribute it and/or modify
-* it under the terms of the GNU General Public License as published
-* by the Free Software Foundation, either version 2 of the License,
-* or (at your option) any later version.
-*
-* VNLib.Utils is distributed in the hope that it will be useful,
-* but WITHOUT ANY WARRANTY; without even the implied warranty of
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-* General Public License for more details.
-*
-* You should have received a copy of the GNU General Public License
-* along with VNLib.Utils. If not, see http://www.gnu.org/licenses/.
-*/
-
-using System;
-
-namespace VNLib.Utils.Resources
-{
- /// <summary>
- /// A concrete <see cref="OpenHandle"/> for a defered operation or a resource that should be released or unwound
- /// when the instance lifetime has ended.
- /// </summary>
- public sealed class CallbackOpenHandle : OpenHandle
- {
- private readonly Action ReleaseFunc;
- /// <summary>
- /// Creates a new generic <see cref="OpenHandle"/> with the specified release callback method
- /// </summary>
- /// <param name="release">The callback function to invoke when the <see cref="OpenHandle"/> is disposed</param>
- public CallbackOpenHandle(Action release) => ReleaseFunc = release;
- ///<inheritdoc/>
- protected override void Free() => ReleaseFunc();
- }
-} \ No newline at end of file
diff --git a/lib/Utils/src/Resources/ManagedLibrary.cs b/lib/Utils/src/Resources/ManagedLibrary.cs
index 786a22d..c899156 100644
--- a/lib/Utils/src/Resources/ManagedLibrary.cs
+++ b/lib/Utils/src/Resources/ManagedLibrary.cs
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2023 Vaughn Nugent
+* Copyright (c) 2024 Vaughn Nugent
*
* Library: VNLib
* Package: VNLib.Utils
@@ -25,7 +25,6 @@
using System;
using System.IO;
using System.Linq;
-using System.Threading;
using System.Reflection;
using System.Runtime.Loader;
using System.Collections.Generic;
@@ -43,7 +42,7 @@ namespace VNLib.Utils.Resources
{
private readonly AssemblyLoadContext _loadContext;
private readonly AssemblyDependencyResolver _resolver;
- private readonly Lazy<Assembly> _lazyAssembly;
+ private readonly LazyInitializer<Assembly> _lazyAssembly;
/// <summary>
/// The absolute path to the assembly file
@@ -53,7 +52,7 @@ namespace VNLib.Utils.Resources
/// <summary>
/// The assembly that is maintained by this loader
/// </summary>
- public Assembly Assembly => _lazyAssembly.Value;
+ public Assembly Assembly => _lazyAssembly.Instance;
/// <summary>
/// Initializes a new <see cref="ManagedLibrary"/> and skips
@@ -74,11 +73,15 @@ namespace VNLib.Utils.Resources
context.ResolvingUnmanagedDll += OnNativeLibraryResolving;
//Lazy load the assembly
- _lazyAssembly = new(LoadAssembly, LazyThreadSafetyMode.PublicationOnly);
+ _lazyAssembly = new(LoadAssembly);
}
//Load the assembly into the parent context
- private Assembly LoadAssembly() => _loadContext.LoadFromAssemblyPath(AssemblyPath);
+ private Assembly LoadAssembly()
+ {
+ AdvancedTrace.WriteLine($"Loading managed library {AssemblyPath} into context {_loadContext.Name}");
+ return _loadContext.LoadFromAssemblyPath(AssemblyPath);
+ }
/// <summary>
/// Raised when the load context that owns this assembly
@@ -91,6 +94,7 @@ namespace VNLib.Utils.Resources
/// </remarks>
protected virtual void OnUnload(AssemblyLoadContext? ctx = null)
{
+ AdvancedTrace.WriteLine($"Unloading managed library {AssemblyPath}");
//Remove resolving event handlers
_loadContext.Unloading -= OnUnload;
_loadContext.Resolving -= OnDependencyResolving;
@@ -111,6 +115,8 @@ namespace VNLib.Utils.Resources
//Resolve the desired asm dependency for the current context
string? requestedDll = _resolver.ResolveUnmanagedDllToPath(libname);
+ AdvancedTrace.WriteLineIf(requestedDll != null,$"Resolving native library {libname} to path {requestedDll} for library {AssemblyPath}");
+
//if the dep is resolved, seach in the assembly directory for the manageed dll only
return requestedDll == null ?
IntPtr.Zero :
@@ -122,6 +128,8 @@ namespace VNLib.Utils.Resources
//Resolve the desired asm dependency for the current context
string? desiredAsm = _resolver.ResolveAssemblyToPath(asmName);
+ AdvancedTrace.WriteLineIf(desiredAsm != null, $"Resolving managed assembly {asmName.Name} to path {desiredAsm} for library {AssemblyPath}");
+
//If the asm exists in the dir, load it
return desiredAsm == null ? null : _loadContext.LoadFromAssemblyPath(desiredAsm);
}
@@ -137,6 +145,8 @@ namespace VNLib.Utils.Resources
//See if the type is exported
Type exp = TryGetExportedType<T>() ?? throw new EntryPointNotFoundException($"Imported assembly does not export desired type {typeof(T).FullName}");
+ AdvancedTrace.WriteLine($"Creating instance of type {exp.FullName} from assembly {AssemblyPath}");
+
//Create instance
return (T)Activator.CreateInstance(exp)!;
}
diff --git a/lib/Utils/src/VNLib.Utils.csproj b/lib/Utils/src/VNLib.Utils.csproj
index bda2164..7941a7b 100644
--- a/lib/Utils/src/VNLib.Utils.csproj
+++ b/lib/Utils/src/VNLib.Utils.csproj
@@ -26,6 +26,10 @@
<PackageRequireLicenseAcceptance>True</PackageRequireLicenseAcceptance>
</PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
+ <DefineConstants>$(DefineConstants);VNLIB_ADVANCED_TRACING</DefineConstants>
+ </PropertyGroup>
+
<ItemGroup>
<None Include="..\README.md">
<Pack>True</Pack>