A game framework written with osu! in mind.
at master 94 lines 3.2 kB view raw
1// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. 2// See the LICENCE file in the repository root for full licence text. 3 4using System; 5using System.Runtime.InteropServices; 6 7namespace osu.Framework.Allocation 8{ 9 /// <summary> 10 /// Wrapper on <see cref="GCHandle" /> that supports the <see cref="IDisposable" /> pattern. 11 /// </summary> 12 public struct ObjectHandle<T> : IDisposable 13 where T : class 14 { 15 /// <summary> 16 /// The pointer from the <see cref="GCHandle" />, if it is allocated. Otherwise <see cref="IntPtr.Zero" />. 17 /// </summary> 18 public IntPtr Handle => handle.IsAllocated ? GCHandle.ToIntPtr(handle) : IntPtr.Zero; 19 20 /// <summary> 21 /// The address of target object, if it is allocated and pinned. Otherwise <see cref="IntPtr.Zero" />. 22 /// Note: This is not the same as the <see cref="Handle" />. 23 /// </summary> 24 public IntPtr Address => handle.IsAllocated ? handle.AddrOfPinnedObject() : IntPtr.Zero; 25 26 public bool IsAllocated => handle.IsAllocated; 27 28 private GCHandle handle; 29 30 private readonly bool fromPointer; 31 32 /// <summary> 33 /// Wraps the provided object with a <see cref="GCHandle" />, using the given <see cref="GCHandleType" />. 34 /// </summary> 35 /// <param name="target">The target object to wrap.</param> 36 /// <param name="handleType">The handle type to use.</param> 37 public ObjectHandle(T target, GCHandleType handleType) 38 { 39 handle = GCHandle.Alloc(target, handleType); 40 fromPointer = false; 41 } 42 43 /// <summary> 44 /// Recreates an <see cref="ObjectHandle{T}" /> based on the passed <see cref="IntPtr" />. 45 /// Disposing this object will not free the handle, the original object must be disposed instead. 46 /// </summary> 47 /// <param name="handle">Handle.</param> 48 public ObjectHandle(IntPtr handle) 49 { 50 this.handle = GCHandle.FromIntPtr(handle); 51 fromPointer = true; 52 } 53 54 /// <summary> 55 /// Gets the object being referenced. 56 /// Returns true if successful and populates <paramref name="target"/> with the referenced object. 57 /// Returns false If the handle is not allocated or the target is not of type <typeparamref name="T"/>. 58 /// </summary> 59 /// <param name="target">Populates this parameter with the targeted object.</param> 60 public bool GetTarget(out T target) 61 { 62 if (!handle.IsAllocated) 63 { 64 target = default; 65 return false; 66 } 67 68 try 69 { 70 if (handle.Target is T value) 71 { 72 target = value; 73 return true; 74 } 75 } 76 catch (InvalidOperationException) 77 { 78 } 79 80 target = default; 81 return false; 82 } 83 84 #region IDisposable Support 85 86 public void Dispose() 87 { 88 if (!fromPointer && handle.IsAllocated) 89 handle.Free(); 90 } 91 92 #endregion 93 } 94}