< Summary

Line coverage
0%
Covered lines: 0
Uncovered lines: 26
Coverable lines: 26
Total lines: 74
Line coverage: 0%
Branch coverage
0%
Covered branches: 0
Total branches: 4
Branch coverage: 0%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Cyclomatic complexity NPath complexity Sequence coverage
.ctor(...)100%110%
Release()0%440%
.ctor(...)100%110%
Dispose()100%110%

File(s)

https://raw.githubusercontent.com/dotnet/runtime/811a7eabb75c42db53440e8ba3f60c07511cfd1f/src/libraries/System.Reflection.Metadata/src/System/Reflection/Internal/MemoryBlocks/MemoryMappedFileBlock.cs

#LineLine coverage
 1// Licensed to the .NET Foundation under one or more agreements.
 2// The .NET Foundation licenses this file to you under the MIT license.
 3
 4using System.Runtime.CompilerServices;
 5using System.Runtime.InteropServices;
 6using System.Threading;
 7
 8namespace System.Reflection.Internal
 9{
 10    internal sealed unsafe class MemoryMappedFileBlock : AbstractMemoryBlock
 11    {
 12        private sealed class DisposableData : CriticalDisposableObject
 13        {
 14            // Usually a MemoryMappedViewAccessor, but kept
 15            // as an IDisposable for better testability.
 16            private IDisposable? _accessor;
 17            private SafeBuffer? _safeBuffer;
 18            private byte* _pointer;
 19
 020            public DisposableData(IDisposable accessor, SafeBuffer safeBuffer, long offset)
 021            {
 22#if FEATURE_CER
 23                // Make sure the current thread isn't aborted in between acquiring the pointer and assigning the fields.
 24                RuntimeHelpers.PrepareConstrainedRegions();
 25                try
 26                { /* intentionally left blank */ }
 27                finally
 28#endif
 029                {
 030                    byte* basePointer = null;
 031                    safeBuffer.AcquirePointer(ref basePointer);
 32
 033                    _accessor = accessor;
 034                    _safeBuffer = safeBuffer;
 035                    _pointer = basePointer + offset;
 036                }
 037            }
 38
 39            protected override void Release()
 040            {
 41#if FEATURE_CER
 42                // Make sure the current thread isn't aborted in between zeroing the references and releasing/disposing.
 43                // Safe buffer only frees the underlying resource if its ref count drops to zero, so we have to make sur
 44                RuntimeHelpers.PrepareConstrainedRegions();
 45                try
 46                { /* intentionally left blank */ }
 47                finally
 48#endif
 049                {
 050                    Interlocked.Exchange(ref _safeBuffer, null)?.ReleasePointer();
 051                    Interlocked.Exchange(ref _accessor, null)?.Dispose();
 052                }
 53
 054                _pointer = null;
 055            }
 56
 057            public byte* Pointer => _pointer;
 58        }
 59
 60        private readonly DisposableData _data;
 61        private readonly int _size;
 62
 063        internal MemoryMappedFileBlock(IDisposable accessor, SafeBuffer safeBuffer, long offset, int size)
 064        {
 065            _data = new DisposableData(accessor, safeBuffer, offset);
 066            _size = size;
 067        }
 68
 069        public override void Dispose() => _data.Dispose();
 070        public override byte* Pointer => _data.Pointer;
 071        public override int Size => _size;
 72    }
 73}
 74