diff options
Diffstat (limited to 'lib/Utils/src')
-rw-r--r-- | lib/Utils/src/Async/IAsyncAccessSerializer.cs | 2 | ||||
-rw-r--r-- | lib/Utils/src/Extensions/MemoryExtensions.cs | 2 | ||||
-rw-r--r-- | lib/Utils/src/Memory/MemoryUtil.cs | 44 | ||||
-rw-r--r-- | lib/Utils/src/Memory/SubSequence.cs | 87 |
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 |