-
Notifications
You must be signed in to change notification settings - Fork 5.1k
Description
Background and Motivation
.NET had acccess to memory mapped files for a long time but using them either requires unsafe pointers, a BinaryReader|Writer like API or Stream
. With the advent of Span
one could access them more easily and pass them directly without intermediate copies / buffers to a larger set of APIs.
Proposed API
We would add
namespace System.IO
{
public class MemoryMappedFile : IDisposable
{
+ public MemoryMappedMemoryManager CreateMemoryManager();
+ public MemoryMappedMemoryManager CreateMemoryManager(long offset, int size);
+ public MemoryMappedMemoryManager CreateMemoryManager(long offset, int size, MemoryMappedFileAccess access);
}
+ public class MemoryMappedMemoryManager : MemoryManager<byte>
+ {
+ }
}
Unlike most other Span
APIs we allow passing long offset
and int size
in order to work with files larger than 2GB which we cannot directly slice into due to all Span
related classes being int length
based. If you need to work with files larger than 2GB, you need to call CreateMemoryManager
with increasing offset
s.
Usage Examples
using MemoryMappedFile file = MemoryMappedFile.CreateFromFile("test.txt");
using MemoryMappedMemoryManager manager = file.CreateMemoryManager();
Memory<byte> memory = manager.Memory;
Console.WriteLine(Encoding.UTF8.GetString(memory.Span));
Alternative Designs
We could also add a string.Create
like API to the MemoryMappedViewAccessor
where MemoryMappedViewAccessor
manages the lifecycle and the design ensures that the Span does not outlive the MemoryMappedViewAccessor
.
namespace System.IO
{
public class MemoryMappedViewAccessor : IDisposable
{
+ public void UseSpan<TState>(TState state, SpanAction<byte, TState> action);
+ public TResult UseSpan<TState, TResult>(TState state, SpanAction<byte, TState> action);
}
which would be used like
using MemoryMappedFile file = MemoryMappedFile.CreateFromFile("test.txt");
using MemoryMappedViewAccessor accessor = file.CreateViewAccessor();
accessor.UseSpan((object)null, (span, state) =>
{
Console.WriteLine(Encoding.UTF8.GetString(span));
});
Risks
Low risk as far as only adding APIs is concerned.
Designs that allow the Span to outlive the memory mapped file could encounter an access violation if trying to use the span past that point.