// Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. #define TRACE using System; using System.Diagnostics; using System.Runtime.InteropServices; using System.Threading; namespace Libuv.Internal { /// /// Summary description for UvMemory /// public abstract class UvMemory : SafeHandle { protected LibuvFunctions _uv; protected int _threadId; protected readonly ILibuvTrace _log; private readonly GCHandleType _handleType; protected UvMemory(ILibuvTrace logger, GCHandleType handleType = GCHandleType.Weak) : base(IntPtr.Zero, true) { _log = logger; _handleType = handleType; } public LibuvFunctions Libuv => _uv; public override bool IsInvalid => handle == IntPtr.Zero; public int ThreadId { get => _threadId; private set => _threadId = value; } protected unsafe void CreateMemory(LibuvFunctions uv, int threadId, int size) { _uv = uv; ThreadId = threadId; handle = Marshal.AllocCoTaskMem(size); *(IntPtr*)handle = GCHandle.ToIntPtr(GCHandle.Alloc(this, _handleType)); } protected static unsafe void DestroyMemory(IntPtr memory) { var gcHandlePtr = *(IntPtr*)memory; DestroyMemory(memory, gcHandlePtr); } protected static void DestroyMemory(IntPtr memory, IntPtr gcHandlePtr) { if (gcHandlePtr != IntPtr.Zero) { var gcHandle = GCHandle.FromIntPtr(gcHandlePtr); gcHandle.Free(); } Marshal.FreeCoTaskMem(memory); } public IntPtr InternalGetHandle() => handle; public void Validate(bool closed = false) { Debug.Assert(closed || !IsClosed, "Handle is closed"); Debug.Assert(!IsInvalid, "Handle is invalid"); Debug.Assert(_threadId == Thread.CurrentThread.ManagedThreadId, "ThreadId is incorrect"); } public static unsafe THandle FromIntPtr(IntPtr handle) { GCHandle gcHandle = GCHandle.FromIntPtr(*(IntPtr*)handle); return (THandle)gcHandle.Target; } } }