Skip to content

Commit

Permalink
Add Embed directive to new APIs (#1137)
Browse files Browse the repository at this point in the history
* #if embed

* increment patch version
  • Loading branch information
j0shuams authored Mar 15, 2022
1 parent beebb01 commit 9b4a4df
Show file tree
Hide file tree
Showing 3 changed files with 137 additions and 127 deletions.
2 changes: 1 addition & 1 deletion build/AzurePipelineTemplates/CsWinRT-Variables.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
variables:
MajorVersion: 1
MinorVersion: 6
PatchVersion: 0
PatchVersion: 1
WinRT.Runtime.AssemblyVersion: '1.6.0.0'
Net5.SDK.Feed: 'https://dotnetcli.blob.core.windows.net/dotnet'
Net5.SDK.Version: '5.0.404'
Expand Down
231 changes: 118 additions & 113 deletions src/WinRT.Runtime/ObjectReference.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright (c) Microsoft Corporation.
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

using System;
Expand Down Expand Up @@ -177,16 +177,16 @@ public virtual unsafe int TryAs<T>(Guid iid, out ObjectReference<T> objRef)
return hr;
}

public virtual unsafe ObjectReference<IUnknownVftbl> AsKnownPtr(IntPtr ptr)
{
AddRef(true);
var objRef = ObjectReference<IUnknownVftbl>.Attach(ref ptr);
objRef.IsAggregated = IsAggregated;
objRef.PreventReleaseOnDispose = IsAggregated;
objRef.ReferenceTrackerPtr = ReferenceTrackerPtr;
return objRef;
}

public virtual unsafe ObjectReference<IUnknownVftbl> AsKnownPtr(IntPtr ptr)
{
AddRef(true);
var objRef = ObjectReference<IUnknownVftbl>.Attach(ref ptr);
objRef.IsAggregated = IsAggregated;
objRef.PreventReleaseOnDispose = IsAggregated;
objRef.ReferenceTrackerPtr = ReferenceTrackerPtr;
return objRef;
}

// Used only as part of the GetInterface implementation where the
// result is an reference passed across the ABI and doesn't need to
// be tracked as an internal reference. This is separate to handle
Expand Down Expand Up @@ -361,22 +361,22 @@ private protected virtual IntPtr GetThisPtrForCurrentContext()
return ThisPtrFromOriginalContext;
}

public ObjectReferenceValue AsValue()
{
// Sharing ptr with objref.
return new ObjectReferenceValue(ThisPtr, IntPtr.Zero, true, this);
}

public unsafe ObjectReferenceValue AsValue(Guid iid)
{
public ObjectReferenceValue AsValue()
{
// Sharing ptr with objref.
return new ObjectReferenceValue(ThisPtr, IntPtr.Zero, true, this);
}

public unsafe ObjectReferenceValue AsValue(Guid iid)
{
Marshal.ThrowExceptionForHR(VftblIUnknown.QueryInterface(ThisPtr, ref iid, out IntPtr thatPtr));
if (IsAggregated)
{
Marshal.Release(thatPtr);
}
AddRefFromTrackerSource();

return new ObjectReferenceValue(thatPtr, ReferenceTrackerPtr, IsAggregated, this);
AddRefFromTrackerSource();

return new ObjectReferenceValue(thatPtr, ReferenceTrackerPtr, IsAggregated, this);
}
}

Expand Down Expand Up @@ -479,10 +479,10 @@ internal sealed class ObjectReferenceWithContext<T> : ObjectReference<T>

private volatile ConcurrentDictionary<IntPtr, ObjectReference<T>> __cachedContext;
private ConcurrentDictionary<IntPtr, ObjectReference<T>> CachedContext => __cachedContext ?? Make_CachedContext();
private ConcurrentDictionary<IntPtr, ObjectReference<T>> Make_CachedContext()
private ConcurrentDictionary<IntPtr, ObjectReference<T>> Make_CachedContext()
{
global::System.Threading.Interlocked.CompareExchange(ref __cachedContext, new(), null);
return __cachedContext;
global::System.Threading.Interlocked.CompareExchange(ref __cachedContext, new(), null);
return __cachedContext;
}

// Agile reference can be null, so whether it is set is tracked separately.
Expand All @@ -495,10 +495,10 @@ private AgileReference Make_AgileReference()

// Set after CallInContext callback given callback can fail to occur.
_isAgileReferenceSet = true;
return __agileReference;

void InitAgileReference()
{
return __agileReference;

void InitAgileReference()
{
global::System.Threading.Interlocked.CompareExchange(ref __agileReference, new AgileReference(this), null);
}
}
Expand Down Expand Up @@ -564,21 +564,21 @@ ObjectReference<T> CreateForCurrentContext(IntPtr _)
return null;
}

try
{
if (_iid == Guid.Empty)
{
return agileReference.Get<T>(GuidGenerator.GetIID(typeof(T)));
}
else
{
return agileReference.Get<T>(_iid);
try
{
if (_iid == Guid.Empty)
{
return agileReference.Get<T>(GuidGenerator.GetIID(typeof(T)));
}
else
{
return agileReference.Get<T>(_iid);
}
}
catch (Exception)
{
// Fallback to using the current context in case of error.
return null;
{
// Fallback to using the current context in case of error.
return null;
}
}
}
Expand All @@ -595,16 +595,16 @@ protected override unsafe void Release()
Context.DisposeContextCallback(_contextCallbackPtr);
}

public override ObjectReference<IUnknownVftbl> AsKnownPtr(IntPtr ptr)
{
AddRef(true);
var objRef = new ObjectReferenceWithContext<IUnknownVftbl>(ptr, Context.GetContextCallback(), Context.GetContextToken())
{
IsAggregated = IsAggregated,
PreventReleaseOnDispose = IsAggregated,
ReferenceTrackerPtr = ReferenceTrackerPtr
};
return objRef;
public override ObjectReference<IUnknownVftbl> AsKnownPtr(IntPtr ptr)
{
AddRef(true);
var objRef = new ObjectReferenceWithContext<IUnknownVftbl>(ptr, Context.GetContextCallback(), Context.GetContextToken())
{
IsAggregated = IsAggregated,
PreventReleaseOnDispose = IsAggregated,
ReferenceTrackerPtr = ReferenceTrackerPtr
};
return objRef;
}

public override unsafe int TryAs<U>(Guid iid, out ObjectReference<U> objRef)
Expand Down Expand Up @@ -632,67 +632,72 @@ public override unsafe int TryAs<U>(Guid iid, out ObjectReference<U> objRef)
}
}

public readonly struct ObjectReferenceValue
{
internal readonly IntPtr ptr;
internal readonly IntPtr referenceTracker;
internal readonly bool preventReleaseOnDispose;
// Used to keep the original IObjectReference alive as we share the same
// referenceTracker instance and in some cases use the same ptr as the
// IObjectReference without an addref (i.e preventReleaseOnDispose).
internal readonly IObjectReference objRef;

internal ObjectReferenceValue(IntPtr ptr) : this()
{
this.ptr = ptr;
}

internal ObjectReferenceValue(IntPtr ptr, IntPtr referenceTracker, bool preventReleaseOnDispose, IObjectReference objRef)
{
this.ptr = ptr;
this.referenceTracker = referenceTracker;
this.preventReleaseOnDispose = preventReleaseOnDispose;
this.objRef = objRef;

}

public static ObjectReferenceValue Attach(ref IntPtr thisPtr)
{
var obj = new ObjectReferenceValue(thisPtr);
thisPtr = IntPtr.Zero;
return obj;
}

public readonly IntPtr GetAbi() => ptr;

public unsafe readonly IntPtr Detach()
{
// If the ptr is not owned by this instance, do an AddRef.
if (preventReleaseOnDispose && ptr != IntPtr.Zero)
{
(**(IUnknownVftbl**)ptr).AddRef(ptr);
}

// Release tracker source reference as it is no longer a managed ref maintained by RCW.
if (referenceTracker != IntPtr.Zero)
{
(**(IReferenceTrackerVftbl**)referenceTracker).ReleaseFromTrackerSource(referenceTracker);
}

return ptr;
}

public unsafe readonly void Dispose()
{
if (referenceTracker != IntPtr.Zero)
{
(**(IReferenceTrackerVftbl**)referenceTracker).ReleaseFromTrackerSource(referenceTracker);
}

if (!preventReleaseOnDispose && ptr != IntPtr.Zero)
{
(**(IUnknownVftbl**)ptr).Release(ptr);
}
}
#if EMBED
internal
#else
public
#endif
readonly struct ObjectReferenceValue
{
internal readonly IntPtr ptr;
internal readonly IntPtr referenceTracker;
internal readonly bool preventReleaseOnDispose;
// Used to keep the original IObjectReference alive as we share the same
// referenceTracker instance and in some cases use the same ptr as the
// IObjectReference without an addref (i.e preventReleaseOnDispose).
internal readonly IObjectReference objRef;

internal ObjectReferenceValue(IntPtr ptr) : this()
{
this.ptr = ptr;
}

internal ObjectReferenceValue(IntPtr ptr, IntPtr referenceTracker, bool preventReleaseOnDispose, IObjectReference objRef)
{
this.ptr = ptr;
this.referenceTracker = referenceTracker;
this.preventReleaseOnDispose = preventReleaseOnDispose;
this.objRef = objRef;

}

public static ObjectReferenceValue Attach(ref IntPtr thisPtr)
{
var obj = new ObjectReferenceValue(thisPtr);
thisPtr = IntPtr.Zero;
return obj;
}

public readonly IntPtr GetAbi() => ptr;

public unsafe readonly IntPtr Detach()
{
// If the ptr is not owned by this instance, do an AddRef.
if (preventReleaseOnDispose && ptr != IntPtr.Zero)
{
(**(IUnknownVftbl**)ptr).AddRef(ptr);
}

// Release tracker source reference as it is no longer a managed ref maintained by RCW.
if (referenceTracker != IntPtr.Zero)
{
(**(IReferenceTrackerVftbl**)referenceTracker).ReleaseFromTrackerSource(referenceTracker);
}

return ptr;
}

public unsafe readonly void Dispose()
{
if (referenceTracker != IntPtr.Zero)
{
(**(IReferenceTrackerVftbl**)referenceTracker).ReleaseFromTrackerSource(referenceTracker);
}

if (!preventReleaseOnDispose && ptr != IntPtr.Zero)
{
(**(IUnknownVftbl**)ptr).Release(ptr);
}
}
}
}
31 changes: 18 additions & 13 deletions src/WinRT.Runtime/Projections/Bindable.net5.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright (c) Microsoft Corporation.
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

using System;
Expand All @@ -24,12 +24,12 @@ internal interface IBindableIterable
[Guid("6A1D6C07-076D-49F2-8314-F52C9C9A8331")]
internal interface IBindableIterator
{
bool MoveNext();
// GetMany is not implemented by IBindableIterator, but it is here
// for compat purposes with WinUI where there are scenarios they do
// reinterpret_cast from IBindableIterator to IIterable<object>. It is
// the last function in the vftable and shouldn't be called by anyone.
// If called, it will return NotImplementedException.
bool MoveNext();
// GetMany is not implemented by IBindableIterator, but it is here
// for compat purposes with WinUI where there are scenarios they do
// reinterpret_cast from IBindableIterator to IIterable<object>. It is
// the last function in the vftable and shouldn't be called by anyone.
// If called, it will return NotImplementedException.
uint GetMany(ref object[] items);
object Current { get; }
bool HasCurrent { get; }
Expand Down Expand Up @@ -123,8 +123,8 @@ private static unsafe int Do_Abi_MoveNext_2(IntPtr thisPtr, byte* result)
return global::WinRT.ExceptionHelpers.GetHRForException(__exception__);
}
return 0;
}

}

[UnmanagedCallersOnly]

private static unsafe int Do_Abi_GetMany_3(IntPtr thisPtr, int __itemsSize, IntPtr items, uint* result)
Expand Down Expand Up @@ -190,8 +190,8 @@ private static unsafe int Do_Abi_get_HasCurrent_1(IntPtr thisPtr, byte* value)
byte __retval = default;
global::WinRT.ExceptionHelpers.ThrowExceptionForHR(_obj.Vftbl.MoveNext_2(ThisPtr, &__retval));
return __retval != 0;
}

}

unsafe uint global::Microsoft.UI.Xaml.Interop.IBindableIterator.GetMany(ref object[] items)
{
// Should never be called.
Expand Down Expand Up @@ -235,7 +235,7 @@ internal static class IBindableIterator_Delegates
{
public unsafe delegate int get_Current_0(IntPtr thisPtr, IntPtr* result);
public unsafe delegate int get_HasCurrent_1(IntPtr thisPtr, byte* result);
public unsafe delegate int MoveNext_2(IntPtr thisPtr, byte* result);
public unsafe delegate int MoveNext_2(IntPtr thisPtr, byte* result);
public unsafe delegate int GetMany_3(IntPtr thisPtr, int itemSize, IntPtr items, uint* result);
}

Expand Down Expand Up @@ -583,7 +583,12 @@ private static FromAbiHelper _AbiHelper(IWinRTObject _this)
}

[global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)]
public static class IEnumerable_Delegates
#if EMBED
internal
#else
public
#endif
static class IEnumerable_Delegates
{
public unsafe delegate int First_0(IntPtr thisPtr, IntPtr* result);
}
Expand Down

0 comments on commit 9b4a4df

Please sign in to comment.