Welcome to mirror list, hosted at ThFree Co, Russian Federation.

UnsafeGCHandle.cs « InteropServices « Runtime « System « src « System.Private.CoreLib « src - github.com/mono/corert.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: 4a0b1d2ce30ce1bb018261a23dff3ed5d109b812 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using System.Diagnostics;
using System.Runtime.CompilerServices;
using System.Threading;

using Internal.Runtime.CompilerServices;

namespace System.Runtime.InteropServices
{
    /// <summary>
    /// The unsafe version of the GCHandle structure.
    /// </summary>
    /// <remarks>
    /// Differences from the <c>GCHandle</c> structure:
    /// <list type="bullet">
    /// <item>The constructor assumes the handle type is valid; no range check is performed.</item>
    /// <item>The pinned flag is not stored in the <c>_handle</c> field.</item>
    /// <item>The <c>Target</c> getter and setter assume the <c>UnsafeGCHandle</c> has been allocated.</item>
    /// <item>No blittable check is performed when allocating a pinned <c>UnsafeGCHandle</c> or setting its target.</item>
    /// <item>The <c>GetRawTargetAddress</c> method returns the raw address of the target (the pointer to
    /// its <c>m_pEEType</c> field).</item>
    /// <item>The <c>Free</c> method is not thread-safe and does not throw if the <c>UnsafeGCHandle</c>
    /// has not been allocated or has been already freed.</item>
    /// </list>
    /// </remarks>
    [StructLayout(LayoutKind.Sequential)]
    public struct UnsafeGCHandle
    {
        // IMPORTANT: This must be kept in sync with the GCHandleType enum.
        private const GCHandleType MaxHandleType = GCHandleType.Pinned;

        // The actual integer handle value that the EE uses internally.
        private IntPtr _handle;

        // Allocate a handle storing the object and the type.
        private UnsafeGCHandle(object value, GCHandleType type)
        {
            Debug.Assert((uint)type <= (uint)MaxHandleType, "Unexpected handle type");
            _handle = RuntimeImports.RhHandleAlloc(value, type);
        }

        public static UnsafeGCHandle Alloc(object value, GCHandleType type)
        {
            return new UnsafeGCHandle(value, type);
        }

        // Target property - allows getting / updating of the handle's referent.
        public object Target
        {
            get
            {
                Debug.Assert(IsAllocated, "Handle is not initialized");
                return RuntimeImports.RhHandleGet(_handle);
            }

            set
            {
                Debug.Assert(IsAllocated, "Handle is not initialized");
                RuntimeImports.RhHandleSet(_handle, value);
            }
        }

        // Frees a GC handle. This method is not thread-safe!
        public void Free()
        {
            if (_handle != default(IntPtr))
            {
                RuntimeImports.RhHandleFree(_handle);
            }
        }

        // Returns the raw address of the target assuming it is pinned.
        public unsafe IntPtr GetRawTargetAddress()
        {
            return *(IntPtr*)_handle;
        }

        // Determine whether this handle has been allocated or not.
        public bool IsAllocated
        {
            get
            {
                return _handle != default(IntPtr);
            }
        }
    }
}