aboutsummaryrefslogtreecommitdiff
path: root/lib/Utils/src
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Utils/src')
-rw-r--r--lib/Utils/src/Async/IAsyncAccessSerializer.cs2
-rw-r--r--lib/Utils/src/Extensions/MemoryExtensions.cs2
-rw-r--r--lib/Utils/src/Memory/MemoryUtil.cs44
-rw-r--r--lib/Utils/src/Memory/SubSequence.cs87
4 files changed, 83 insertions, 52 deletions
diff --git a/lib/Utils/src/Async/IAsyncAccessSerializer.cs b/lib/Utils/src/Async/IAsyncAccessSerializer.cs
index 5dce3cd..75f5dd6 100644
--- a/lib/Utils/src/Async/IAsyncAccessSerializer.cs
+++ b/lib/Utils/src/Async/IAsyncAccessSerializer.cs
@@ -28,7 +28,7 @@ using System.Threading.Tasks;
namespace VNLib.Utils.Async
{
/// <summary>
- /// A mutual exclusion primitive that provides asynchronous waites for serialized
+ /// A mutual exclusion primitive that provides asynchronous waits for serialized
/// access to a resource based on a moniker. Similar to the <see cref="Monitor"/>
/// class.
/// </summary>
diff --git a/lib/Utils/src/Extensions/MemoryExtensions.cs b/lib/Utils/src/Extensions/MemoryExtensions.cs
index 237a567..0e898b4 100644
--- a/lib/Utils/src/Extensions/MemoryExtensions.cs
+++ b/lib/Utils/src/Extensions/MemoryExtensions.cs
@@ -308,6 +308,7 @@ namespace VNLib.Utils.Extensions
/// <param name="offset">An offset within the handle</param>
/// <param name="size">The size of the window</param>
/// <returns>The new <see cref="SubSequence{T}"/> within the block</returns>
+ /// <exception cref="ArgumentOutOfRangeException"></exception>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static SubSequence<T> GetSubSequence<T>(this MemoryHandle<T> block, nuint offset, int size) where T : unmanaged => new (block, offset, size);
@@ -319,6 +320,7 @@ namespace VNLib.Utils.Extensions
/// <param name="offset">An offset within the handle</param>
/// <param name="size">The size of the window</param>
/// <returns>The new <see cref="SubSequence{T}"/> within the block</returns>
+ /// <exception cref="ArgumentOutOfRangeException"></exception>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static SubSequence<T> GetSubSequence<T>(this MemoryHandle<T> block, nint offset, int size) where T : unmanaged
{
diff --git a/lib/Utils/src/Memory/MemoryUtil.cs b/lib/Utils/src/Memory/MemoryUtil.cs
index e802360..1be46e4 100644
--- a/lib/Utils/src/Memory/MemoryUtil.cs
+++ b/lib/Utils/src/Memory/MemoryUtil.cs
@@ -81,6 +81,8 @@ namespace VNLib.Utils.Memory
/// heap.
/// </summary>
public const int MAX_UNSAFE_POOL_SIZE = 80 * 1024;
+
+ private static readonly int SystemPageSize = Environment.SystemPageSize;
/// <summary>
/// Provides a shared heap instance for the process to allocate memory from.
@@ -166,19 +168,19 @@ namespace VNLib.Utils.Memory
IUnmangedHeap heap;
+ ERRNO userFlags = 0;
+
+ //Try to parse the raw flags to pass to the heap
+ if (nint.TryParse(rawFlagsEnv, NumberStyles.HexNumber, null, out nint result))
+ {
+ userFlags = new(result);
+ }
+
//Check for heap api dll
if (!string.IsNullOrWhiteSpace(heapDllPath))
{
- ERRNO rawFlags = 0;
-
- //Try to parse the raw flags to pass to the heap
- if (nint.TryParse(rawFlagsEnv, NumberStyles.HexNumber, null, out nint result))
- {
- rawFlags = new(result);
- }
-
//Attempt to load the heap
- heap = NativeHeap.LoadHeap(heapDllPath, DllImportSearchPath.SafeDirectories, cFlags, rawFlags);
+ heap = NativeHeap.LoadHeap(heapDllPath, DllImportSearchPath.SafeDirectories, cFlags, userFlags);
}
//No user heap was specified, use fallback
else if (IsWindows)
@@ -192,10 +194,10 @@ namespace VNLib.Utils.Memory
if (!nuint.TryParse(sharedSize, out nuint defaultSize))
{
defaultSize = SHARED_HEAP_INIT_SIZE;
- }
+ }
//Create win32 private heap
- heap = Win32PrivateHeap.Create(defaultSize, cFlags);
+ heap = Win32PrivateHeap.Create(defaultSize, cFlags, flags:userFlags);
}
else
{
@@ -591,7 +593,7 @@ namespace VNLib.Utils.Memory
{
if (offset + count > handle.Length)
{
- throw new ArgumentException("The offset or count is outside of the range of the block of memory");
+ throw new ArgumentOutOfRangeException("The offset or count is outside of the range of the block of memory");
}
}
@@ -686,6 +688,16 @@ namespace VNLib.Utils.Memory
public static Span<T> GetSpan<T>(IntPtr address, int size) => new(address.ToPointer(), size);
/// <summary>
+ /// Gets a <see cref="Span{T}"/> over the block of memory pointed to by the supplied handle.
+ /// </summary>
+ /// <typeparam name="T"></typeparam>
+ /// <param name="handle"></param>
+ /// <param name="size">The size of the span (the size of the block)</param>
+ /// <returns>A span over the block of memory pointed to by the handle of the specified size</returns>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static Span<T> GetSpan<T>(MemoryHandle handle, int size) => new(handle.Pointer, size);
+
+ /// <summary>
/// Rounds the requested byte size up to the nearest page
/// number of bytes
/// </summary>
@@ -695,10 +707,10 @@ namespace VNLib.Utils.Memory
public static nuint NearestPage(nuint byteSize)
{
//Get page count by dividing count by number of pages
- nuint pages = (uint)Math.Ceiling(byteSize / (double)Environment.SystemPageSize);
+ nuint pages = (uint)Math.Ceiling(byteSize / (double)SystemPageSize);
//Multiply back to page sizes
- return pages * (nuint)Environment.SystemPageSize;
+ return pages * (nuint)SystemPageSize;
}
/// <summary>
@@ -711,10 +723,10 @@ namespace VNLib.Utils.Memory
public static nint NearestPage(nint byteSize)
{
//Get page count by dividing count by number of pages
- nint pages = (int)Math.Ceiling(byteSize / (double)Environment.SystemPageSize);
+ nint pages = (int)Math.Ceiling(byteSize / (double)SystemPageSize);
//Multiply back to page sizes
- return pages * Environment.SystemPageSize;
+ return pages * SystemPageSize;
}
}
} \ No newline at end of file
diff --git a/lib/Utils/src/Memory/SubSequence.cs b/lib/Utils/src/Memory/SubSequence.cs
index 87e369b..4e3c22c 100644
--- a/lib/Utils/src/Memory/SubSequence.cs
+++ b/lib/Utils/src/Memory/SubSequence.cs
@@ -32,10 +32,19 @@ namespace VNLib.Utils.Memory
/// Represents a subset (or window) of data within a <see cref="MemoryHandle{T}"/>
/// </summary>
/// <typeparam name="T">The unmanaged type to wrap</typeparam>
- public readonly struct SubSequence<T> : IEquatable<SubSequence<T>> where T: unmanaged
+ public readonly record struct SubSequence<T> where T: unmanaged
{
- private readonly MemoryHandle<T> _handle;
- private readonly nuint _offset;
+ readonly nuint _offset;
+
+ /// <summary>
+ /// The handle that owns the memory block
+ /// </summary>
+ public readonly MemoryHandle<T> Handle { get; }
+
+ /// <summary>
+ /// The number of elements in the current sequence
+ /// </summary>
+ public readonly int Size { get; }
/// <summary>
/// Creates a new <see cref="SubSequence{T}"/> to the handle to get a window of the block
@@ -43,23 +52,25 @@ namespace VNLib.Utils.Memory
/// <param name="block"></param>
/// <param name="offset"></param>
/// <param name="size"></param>
+ /// <exception cref="ArgumentNullException"></exception>
+ /// <exception cref="ArgumentOutOfRangeException"></exception>
public SubSequence(MemoryHandle<T> block, nuint offset, int size)
{
- _offset = offset;
+ Handle = block ?? throw new ArgumentNullException(nameof(block));
Size = size >= 0 ? size : throw new ArgumentOutOfRangeException(nameof(size));
- _handle = block ?? throw new ArgumentNullException(nameof(block));
- }
+ _offset = offset;
- /// <summary>
- /// The number of elements in the current window
- /// </summary>
- public readonly int Size { get; }
+ //Check handle bounds
+ MemoryUtil.CheckBounds(block, offset, (uint)size);
+ }
+
/// <summary>
/// Gets a <see cref="Span{T}"/> that is offset from the base of the handle
+ /// and the size of the current sequence
/// </summary>
/// <exception cref="ArgumentOutOfRangeException"></exception>
- public readonly Span<T> Span => Size > 0 ? _handle.GetOffsetSpan(_offset, Size) : Span<T>.Empty;
+ public readonly Span<T> Span => Size > 0 ? Handle.GetOffsetSpan(_offset, Size) : Span<T>.Empty;
/// <summary>
/// Slices the current sequence into a smaller <see cref="SubSequence{T}"/>
@@ -67,34 +78,40 @@ namespace VNLib.Utils.Memory
/// <param name="offset">The relative offset from the current window offset</param>
/// <param name="size">The size of the block</param>
/// <returns>A <see cref="SubSequence{T}"/> of the current sequence</returns>
- public readonly SubSequence<T> Slice(nuint offset, int size) => new (_handle, checked(_offset + offset), size);
-
- /// <summary>
- /// Returns the signed 32-bit hashcode
- /// </summary>
- /// <returns>A signed 32-bit integer that represents the hashcode for the current instance</returns>
- /// <exception cref="ObjectDisposedException"></exception>
- public readonly override int GetHashCode() => _handle.GetHashCode() + _offset.GetHashCode();
+ public readonly SubSequence<T> Slice(nuint offset, int size)
+ {
+ //Calc offset
+ nuint newOffset = checked(_offset + offset);
+
+ //Cal max size after the slice
+ int newMaxSize = Size - (int)offset;
- ///<inheritdoc/>
- public readonly bool Equals(SubSequence<T> other) => Span.SequenceEqual(other.Span);
+ if(newMaxSize < 0)
+ {
+ throw new ArgumentOutOfRangeException(nameof(offset));
+ }
- ///<inheritdoc/>
- public readonly override bool Equals(object? obj) => obj is SubSequence<T> other && Equals(other);
+ if(size > newMaxSize)
+ {
+ throw new ArgumentOutOfRangeException(nameof(size));
+ }
+ return new SubSequence<T>(Handle, newOffset, size > newMaxSize ? newMaxSize : size);
+ }
/// <summary>
- /// Determines if two <see cref="SubSequence{T}"/> are equal
- /// </summary>
- /// <param name="left"></param>
- /// <param name="right"></param>
- /// <returns>True if the sequences are equal, false otherwise</returns>
- public static bool operator ==(SubSequence<T> left, SubSequence<T> right) => left.Equals(right);
- /// <summary>
- /// Determines if two <see cref="SubSequence{T}"/> are not equal
+ /// Slices the current sequence into a smaller <see cref="SubSequence{T}"/>
/// </summary>
- /// <param name="left"></param>
- /// <param name="right"></param>
- /// <returns>True if the sequences are not equal, false otherwise</returns>
- public static bool operator !=(SubSequence<T> left, SubSequence<T> right) => !left.Equals(right);
+ /// <param name="offset">The relative offset from the current window offset</param>
+ /// <returns>A <see cref="SubSequence{T}"/> of the current sequence</returns>
+ public readonly SubSequence<T> Slice(nuint offset)
+ {
+ //Calc offset
+ nuint newOffset = _offset + offset;
+
+ //Calc the new max size of the block (let constructor handle the exception if less than 0)
+ int newMaxSize = (int)((nuint)Size - offset);
+
+ return new SubSequence<T>(Handle, newOffset, newMaxSize);
+ }
}
} \ No newline at end of file