| File: System\Reflection\Internal\MemoryBlocks\MemoryMappedFileBlock.cs | Web Access |
| Project: src\runtime\src\libraries\System.Reflection.Metadata\src\System.Reflection.Metadata.csproj (System.Reflection.Metadata) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Threading; namespace System.Reflection.Internal { internal sealed unsafe class MemoryMappedFileBlock : AbstractMemoryBlock { private sealed class DisposableData : CriticalDisposableObject { // Usually a MemoryMappedViewAccessor, but kept // as an IDisposable for better testability. private IDisposable? _accessor; private SafeBuffer? _safeBuffer; private byte* _pointer; public DisposableData(IDisposable accessor, SafeBuffer safeBuffer, long offset) { #if FEATURE_CER // Make sure the current thread isn't aborted in between acquiring the pointer and assigning the fields. RuntimeHelpers.PrepareConstrainedRegions(); try { /* intentionally left blank */ } finally #endif { byte* basePointer = null; safeBuffer.AcquirePointer(ref basePointer); _accessor = accessor; _safeBuffer = safeBuffer; _pointer = basePointer + offset; } } protected override void Release() { #if FEATURE_CER // Make sure the current thread isn't aborted in between zeroing the references and releasing/disposing. // Safe buffer only frees the underlying resource if its ref count drops to zero, so we have to make sure it does. RuntimeHelpers.PrepareConstrainedRegions(); try { /* intentionally left blank */ } finally #endif { Interlocked.Exchange(ref _safeBuffer, null)?.ReleasePointer(); Interlocked.Exchange(ref _accessor, null)?.Dispose(); } _pointer = null; } public byte* Pointer => _pointer; } private readonly DisposableData _data; private readonly int _size; internal MemoryMappedFileBlock(IDisposable accessor, SafeBuffer safeBuffer, long offset, int size) { _data = new DisposableData(accessor, safeBuffer, offset); _size = size; } public override void Dispose() => _data.Dispose(); public override byte* Pointer => _data.Pointer; public override int Size => _size; } }