File: System\Reflection\Internal\MemoryBlocks\NativeHeapMemoryBlock.cs
Web Access
Project: src\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
{
    /// <summary>
    /// Represents memory block allocated on native heap.
    /// </summary>
    /// <remarks>
    /// Owns the native memory resource.
    /// </remarks>
    internal sealed class NativeHeapMemoryBlock : AbstractMemoryBlock
    {
        private sealed unsafe class DisposableData : CriticalDisposableObject
        {
            private IntPtr _pointer;
 
            public DisposableData(int size)
            {
#if FEATURE_CER
                // make sure the current thread isn't aborted in between allocating and storing the pointer
                RuntimeHelpers.PrepareConstrainedRegions();
                try
                { /* intentionally left blank */ }
                finally
#endif
                {
                    _pointer = Marshal.AllocHGlobal(size);
                }
            }
 
            protected override void Release()
            {
#if FEATURE_CER
                // make sure the current thread isn't aborted in between zeroing the pointer and freeing the memory
                RuntimeHelpers.PrepareConstrainedRegions();
                try
                { /* intentionally left blank */ }
                finally
#endif
                {
                    IntPtr ptr = Interlocked.Exchange(ref _pointer, IntPtr.Zero);
                    if (ptr != IntPtr.Zero)
                    {
                        Marshal.FreeHGlobal(ptr);
                    }
                }
            }
 
            public byte* Pointer => (byte*)_pointer;
        }
 
        private readonly DisposableData _data;
        private readonly int _size;
 
        internal NativeHeapMemoryBlock(int size)
        {
            _data = new DisposableData(size);
            _size = size;
        }
 
        public override void Dispose() => _data.Dispose();
        public override unsafe byte* Pointer => _data.Pointer;
        public override int Size => _size;
    }
}