Skip to content

Commit

Permalink
Remove Lazy<T> uses on NativeAOT
Browse files Browse the repository at this point in the history
  • Loading branch information
Sergio0694 committed Jan 26, 2024
1 parent c989f44 commit 338c7d3
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 8 deletions.
31 changes: 26 additions & 5 deletions src/WinRT.Runtime/AgileReference.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// Licensed under the MIT License.

using System;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using WinRT.Interop;

Expand All @@ -15,7 +16,27 @@ namespace WinRT
class AgileReference : IDisposable
{
private readonly static Guid CLSID_StdGlobalInterfaceTable = new(0x00000323, 0, 0, 0xc0, 0, 0, 0, 0, 0, 0, 0x46);
private readonly static Lazy<IGlobalInterfaceTable> Git = new Lazy<IGlobalInterfaceTable>(() => GetGitTable());
private static readonly object _lock = new();
private static volatile IGlobalInterfaceTable _git;

// Simple singleton lazy-initialization scheme (and saving the Lazy<T> size)
internal static IGlobalInterfaceTable Git
{
get
{
return _git ?? Git_Slow();

[MethodImpl(MethodImplOptions.NoInlining)]
static IGlobalInterfaceTable Git_Slow()
{
lock (_lock)
{
return _git ??= GetGitTable();
}
}
}
}

private readonly IObjectReference _agileReference;
private readonly IntPtr _cookie;
private bool disposed;
Expand Down Expand Up @@ -50,7 +71,7 @@ internal unsafe AgileReference(IntPtr thisPtr)
}
catch (TypeLoadException)
{
_cookie = Git.Value.RegisterInterfaceInGlobal(thisPtr, iid);
_cookie = Git.RegisterInterfaceInGlobal(thisPtr, iid);
}
finally
{
Expand All @@ -59,9 +80,9 @@ internal unsafe AgileReference(IntPtr thisPtr)
}


public IObjectReference Get() => _cookie == IntPtr.Zero ? ABI.WinRT.Interop.IAgileReferenceMethods.Resolve(_agileReference, IUnknownVftbl.IID) : Git.Value?.GetInterfaceFromGlobal(_cookie, IUnknownVftbl.IID);
public IObjectReference Get() => _cookie == IntPtr.Zero ? ABI.WinRT.Interop.IAgileReferenceMethods.Resolve(_agileReference, IUnknownVftbl.IID) : Git.GetInterfaceFromGlobal(_cookie, IUnknownVftbl.IID);

internal ObjectReference<T> Get<T>(Guid iid) => _cookie == IntPtr.Zero ? ABI.WinRT.Interop.IAgileReferenceMethods.Resolve<T>(_agileReference, iid) : Git.Value?.GetInterfaceFromGlobal(_cookie, IUnknownVftbl.IID)?.As<T>(iid);
internal ObjectReference<T> Get<T>(Guid iid) => _cookie == IntPtr.Zero ? ABI.WinRT.Interop.IAgileReferenceMethods.Resolve<T>(_agileReference, iid) : Git?.GetInterfaceFromGlobal(_cookie, IUnknownVftbl.IID)?.As<T>(iid);

protected virtual void Dispose(bool disposing)
{
Expand All @@ -71,7 +92,7 @@ protected virtual void Dispose(bool disposing)
{
try
{
Git.Value.RevokeInterfaceFromGlobal(_cookie);
Git.RevokeInterfaceFromGlobal(_cookie);
}
catch(ArgumentException)
{
Expand Down
2 changes: 1 addition & 1 deletion src/WinRT.Runtime/ComWrappersSupport.cs
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ internal unsafe static bool IsFreeThreaded(IntPtr iUnknown)
Guid iid_unmarshalClass;
Marshal.ThrowExceptionForHR((**(ABI.WinRT.Interop.IMarshal.Vftbl**)marshalPtr).GetUnmarshalClass_0(
marshalPtr, &iid_IUnknown, IntPtr.Zero, MSHCTX.InProc, IntPtr.Zero, MSHLFLAGS.Normal, &iid_unmarshalClass));
if (iid_unmarshalClass == ABI.WinRT.Interop.IMarshal.IID_InProcFreeThreadedMarshaler.Value)
if (iid_unmarshalClass == ABI.WinRT.Interop.IMarshal.IID_InProcFreeThreadedMarshaler)
{
return true;
}
Expand Down
30 changes: 28 additions & 2 deletions src/WinRT.Runtime/Interop/IMarshal.cs
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,35 @@ internal sealed class IMarshal
[DllImport("api-ms-win-core-com-l1-1-0.dll")]
private static extern unsafe int CoCreateFreeThreadedMarshaler(IntPtr outer, IntPtr* marshalerPtr);

private static readonly string NotImplemented_NativeRoutineNotFound = "A native library routine was not found: {0}.";
private const string NotImplemented_NativeRoutineNotFound = "A native library routine was not found: {0}.";

internal static readonly Lazy<Guid> IID_InProcFreeThreadedMarshaler = new Lazy<Guid>(Vftbl.GetInProcFreeThreadedMarshalerIID);
private static readonly object _IID_InProcFreeThreadedMarshalerLock = new();
internal static volatile object _IID_InProcFreeThreadedMarshaler;

// Simple singleton lazy-initialization scheme (and saving the Lazy<T> size)
internal static Guid IID_InProcFreeThreadedMarshaler
{
get
{
object iid = _IID_InProcFreeThreadedMarshaler;

if (iid is not null)
{
return (Guid)iid;
}

return IID_InProcFreeThreadedMarshaler_Slow();

[MethodImpl(MethodImplOptions.NoInlining)]
static Guid IID_InProcFreeThreadedMarshaler_Slow()
{
lock (_IID_InProcFreeThreadedMarshalerLock)
{
return (Guid)(_IID_InProcFreeThreadedMarshaler ??= Vftbl.GetInProcFreeThreadedMarshalerIID());
}
}
}
}

[Guid("00000003-0000-0000-c000-000000000046")]
public unsafe struct Vftbl
Expand Down

0 comments on commit 338c7d3

Please sign in to comment.