File: System\Reflection\Internal\Utilities\PinnedObject.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
{
    internal sealed class PinnedObject : CriticalDisposableObject
    {
        // can't be read-only since GCHandle is a mutable struct
        private GCHandle _handle;
 
        // non-zero indicates a valid handle
        private int _isValid;
 
        public PinnedObject(object obj)
        {
#if FEATURE_CER
            // Make sure the current thread isn't aborted in between allocating the handle and storing it.
            RuntimeHelpers.PrepareConstrainedRegions();
            try
            { /* intentionally left blank */ }
            finally
#endif
            {
                _handle = GCHandle.Alloc(obj, GCHandleType.Pinned);
                _isValid = 1;
            }
        }
 
        protected override void Release()
        {
#if FEATURE_CER
            // Make sure the current thread isn't aborted in between zeroing the handle and freeing it.
            RuntimeHelpers.PrepareConstrainedRegions();
            try
            { /* intentionally left blank */ }
            finally
#endif
            {
                if (Interlocked.Exchange(ref _isValid, 0) != 0)
                {
                    _handle.Free();
                }
            }
        }
 
        public unsafe byte* Pointer => (byte*)_handle.AddrOfPinnedObject();
    }
}