aboutsummaryrefslogtreecommitdiff
path: root/lib/Utils/src
diff options
context:
space:
mode:
authorLibravatar vnugent <public@vaughnnugent.com>2024-06-26 21:01:15 -0400
committerLibravatar vnugent <public@vaughnnugent.com>2024-06-26 21:01:15 -0400
commit12391e9a207b60b41a074600fc2373ad3eb1c3ab (patch)
tree5a3396a889a2226aaabdf9aee5cd7cb4f5b04e31 /lib/Utils/src
parent92e182ceaf843f8d859d38faa8b2c0ff53207ff6 (diff)
feat(server): Server arch update, Memory struct access
Diffstat (limited to 'lib/Utils/src')
-rw-r--r--lib/Utils/src/IO/VnMemoryStream.cs58
1 files changed, 51 insertions, 7 deletions
diff --git a/lib/Utils/src/IO/VnMemoryStream.cs b/lib/Utils/src/IO/VnMemoryStream.cs
index 2c604b2..4d51a08 100644
--- a/lib/Utils/src/IO/VnMemoryStream.cs
+++ b/lib/Utils/src/IO/VnMemoryStream.cs
@@ -49,9 +49,13 @@ namespace VNLib.Utils.IO
//Memory
private readonly IResizeableMemoryHandle<byte> _buffer;
+
//Default owns handle
private readonly bool OwnsHandle = true;
+ //Lazy loaded memory wrapper
+ private MemoryManager<byte>? _memoryWrapper;
+
/// <summary>
/// Creates a new <see cref="VnMemoryStream"/> pointing to the begining of memory, and consumes the handle.
/// </summary>
@@ -259,27 +263,31 @@ namespace VNLib.Utils.IO
cancellationToken.ThrowIfCancellationRequested();
+ //Memory manager requires 32bit or less in length
if(_length < Int32.MaxValue)
{
- //Safe to alloc a memory manager to do copy
- using MemoryManager<byte> asMemManager = _buffer.ToMemoryManager(false);
+ //Get/alloc the internal memory manager and get the block
+ ReadOnlyMemory<byte> asMemory = AsMemory();
+
+ Debug.Assert(asMemory.Length >= LenToPosDiff, "Internal memory block smaller than desired for stream copy");
/*
* CopyTo starts at the current position, as if calling Read()
* so the reader must be offset to match and the _length gives us the
* actual length of the stream and therefor the segment size
- */
+ */
- while(LenToPosDiff > 0)
+ while (LenToPosDiff > 0)
{
int blockSize = Math.Min((int)LenToPosDiff, bufferSize);
- Memory<byte> window = asMemManager.Memory.Slice((int)_position, blockSize);
+
+ ReadOnlyMemory<byte> window = asMemory.Slice((int)_position, blockSize);
//write async
await destination.WriteAsync(window, cancellationToken);
//Update position
- _position+= bufferSize;
+ _position += bufferSize;
}
}
else
@@ -581,6 +589,40 @@ namespace VNLib.Utils.IO
//Get span with no offset
return _buffer.AsSpan(0, len);
}
+
+ /// <summary>
+ /// Returns a <see cref="ReadOnlyMemory{T}"/> structure which is a window of the buffered
+ /// data as it currently sits. For writeable straems, you must call this function
+ /// every time the size of the stream changes. The memory structure is just a "pointer" to
+ /// the internal buffer.
+ /// </summary>
+ /// <returns>
+ /// A memory snapshot of the stream.
+ /// </returns>
+ /// <remarks>
+ /// This function causes an internal allocation on the first call. After the first call
+ /// to this function, all calls are thread-safe.
+ /// </remarks>
+ public ReadOnlyMemory<byte> AsMemory()
+ {
+ /*
+ * Safe cast stram length to int, because memory window requires a 32bit
+ * integer. Also will throw before allocating the mmemory manager
+ */
+
+ int len = Convert.ToInt32(_length);
+
+ //Defer/lazy init the memory manager
+ MemoryManager<byte> asMemory = LazyInitializer.EnsureInitialized(ref _memoryWrapper, AllocMemManager);
+
+ Debug.Assert(asMemory != null);
+
+ /*
+ * Buffer window may be larger than the actual stream legnth, so
+ * slice the memory to the actual length of the stream
+ */
+ return asMemory.Memory[..len];
+ }
/// <summary>
/// If the current stream is a readonly stream, creates a shallow copy for reading only.
@@ -589,5 +631,7 @@ namespace VNLib.Utils.IO
/// <exception cref="NotSupportedException"></exception>
public object Clone() => GetReadonlyShallowCopy();
+ private MemoryManager<byte> AllocMemManager() => _buffer.ToMemoryManager(false);
+
}
-} \ No newline at end of file
+}