File: src\libraries\Common\src\System\IO\MemoryMappedFiles\MemoryMappedFileMemoryManager.cs
Web Access
Project: src\src\libraries\System.Security.Cryptography\src\System.Security.Cryptography.csproj (System.Security.Cryptography)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
 
using System.Buffers;
 
namespace System.IO.MemoryMappedFiles
{
    internal sealed unsafe class MemoryMappedFileMemoryManager : MemoryManager<byte>
    {
        private byte* _pointer;
        private int _length;
        private MemoryMappedFile _mappedFile;
        private MemoryMappedViewAccessor _accessor;
 
        public MemoryMappedFileMemoryManager(
            byte* pointer,
            int length,
            MemoryMappedFile mappedFile,
            MemoryMappedViewAccessor accessor)
        {
            _pointer = pointer;
            _length = length;
            _mappedFile = mappedFile;
            _accessor = accessor;
        }
 
#if DEBUG
#pragma warning disable CA2015
        ~MemoryMappedFileMemoryManager()
#pragma warning restore CA2015
        {
            Environment.FailFast("MemoryMappedFileMemoryManager was finalized.");
        }
#endif
 
        internal static MemoryMappedFileMemoryManager CreateFromFileClamped(
            FileStream fileStream,
            MemoryMappedFileAccess access = MemoryMappedFileAccess.Read,
            HandleInheritability inheritability = HandleInheritability.None,
            bool leaveOpen = false)
        {
            int length = (int)Math.Min(int.MaxValue, fileStream.Length);
            MemoryMappedFile mapped = MemoryMappedFile.CreateFromFile(fileStream, null, 0, access, inheritability, leaveOpen);
            MemoryMappedViewAccessor? accessor = null;
            byte* pointer = null;
 
            try
            {
                accessor = mapped.CreateViewAccessor(0, length, access);
                accessor.SafeMemoryMappedViewHandle.AcquirePointer(ref pointer);
 
                return new MemoryMappedFileMemoryManager(pointer, length, mapped, accessor);
            }
            catch (Exception)
            {
                if (pointer != null)
                {
                    accessor!.SafeMemoryMappedViewHandle.ReleasePointer();
                }
 
                accessor?.Dispose();
                mapped.Dispose();
                throw;
            }
        }
 
        protected override void Dispose(bool disposing)
        {
            _pointer = null;
            _length = -1;
            _accessor?.SafeMemoryMappedViewHandle.ReleasePointer();
            _accessor?.Dispose();
            _mappedFile?.Dispose();
            _accessor = null!;
            _mappedFile = null!;
        }
 
        public override Span<byte> GetSpan()
        {
            ThrowIfDisposed();
            return new Span<byte>(_pointer, _length);
        }
 
        public override MemoryHandle Pin(int elementIndex = 0)
        {
            ThrowIfDisposed();
            return default;
        }
 
        public override void Unpin()
        {
            ThrowIfDisposed();
            // nop
        }
 
        private void ThrowIfDisposed()
        {
#if NET
            ObjectDisposedException.ThrowIf(_length < 0, this);
#else
            if (_length < 0)
            {
                throw new ObjectDisposedException(GetType().FullName);
            }
#endif
        }
    }
}