Skip to content

Commit

Permalink
Fix.
Browse files Browse the repository at this point in the history
  • Loading branch information
jlaanstra committed Nov 3, 2023
1 parent 104f491 commit 73d5e29
Showing 1 changed file with 29 additions and 49 deletions.
78 changes: 29 additions & 49 deletions src/cswinrt/strings/WinRT.cs
Original file line number Diff line number Diff line change
Expand Up @@ -493,41 +493,28 @@ public static unsafe (IObjectReference obj, int hr) GetActivationFactory(string
}
}

#if NET6_0_OR_GREATER
internal interface IHasGuid
{
#pragma warning disable CA2252 // This API requires opting into preview features
static abstract global::System.Guid IID { get; }
#pragma warning restore CA2252 // This API requires opting into preview features
}
#endif

internal class BaseActivationFactory
{
private volatile ObjectReference<IActivationFactoryVftbl> _IActivationFactory;
private Tuple<ObjectReference<IActivationFactoryVftbl>, IntPtr> _IActivationFactory;

public ObjectReference<IActivationFactoryVftbl> Value
{
get
{
var existingInstance = _IActivationFactory;
if (existingInstance != null && (_contextToken == IntPtr.Zero || _contextToken == Context.GetContextToken()))
if (existingInstance != null && (existingInstance.Item2 == IntPtr.Zero || existingInstance.Item2 == Context.GetContextToken()))
{
return existingInstance;
return existingInstance.Item1;
}

(var newFactory, var newToken) = InitializeFactory();
if (Interlocked.CompareExchange(ref _IActivationFactory, newFactory, existingInstance) == existingInstance)
{
_contextToken = newToken;
}
return newFactory;
var newFactory = InitializeFactory();
Interlocked.CompareExchange(ref _IActivationFactory, newFactory, existingInstance);
return newFactory.Item1;
}
}

private readonly string namespaceName;
private readonly string typeName;
private IntPtr _contextToken;

public I AsInterface<I>() => Value.AsInterface<I>();
public ObjectReference<I> As<I>() => Value.As<I>();
Expand All @@ -536,12 +523,10 @@ public ObjectReference<IActivationFactoryVftbl> Value
public BaseActivationFactory(string namespaceName, string typeName)
{
this.namespaceName = namespaceName;
this.typeName = typeName;

(this._IActivationFactory, this._contextToken) = InitializeFactory();
this.typeName = typeName;
}

private (ObjectReference<IActivationFactoryVftbl>, IntPtr) InitializeFactory()
private Tuple<ObjectReference<IActivationFactoryVftbl>, IntPtr> InitializeFactory()
{
// Prefer the RoGetActivationFactory HRESULT failure over the LoadLibrary/etc. failure
int hr;
Expand All @@ -550,7 +535,7 @@ public BaseActivationFactory(string namespaceName, string typeName)
if (newFactory != null)
{
var newContextToken = Context.IsFreeThreaded(newFactory) ? IntPtr.Zero : Context.GetContextToken();
return (newFactory, newContextToken);
return Tuple.Create(newFactory, newContextToken);
}

var moduleName = namespaceName;
Expand All @@ -563,7 +548,7 @@ public BaseActivationFactory(string namespaceName, string typeName)
if (newFactory != null)
{
var newContextToken = Context.IsFreeThreaded(newFactory) ? IntPtr.Zero : Context.GetContextToken();
return (newFactory, newContextToken);
return Tuple.Create(newFactory, newContextToken);
}
}

Expand All @@ -583,7 +568,8 @@ public BaseActivationFactory(string namespaceName, string typeName)
public unsafe ObjectReference<I> _ActivateInstance<I>()
{
IntPtr instancePtr;
Marshal.ThrowExceptionForHR(Value.Vftbl.ActivateInstance(_IActivationFactory.ThisPtr, &instancePtr));
var value = Value;
Marshal.ThrowExceptionForHR(value.Vftbl.ActivateInstance(value.ThisPtr, &instancePtr));
try
{
return ComWrappersSupport.GetObjectReferenceForInterface<I>(instancePtr);
Expand All @@ -594,8 +580,8 @@ public unsafe ObjectReference<I> _ActivateInstance<I>()
}
}

public ObjectReference<I> _As<I>() => _IActivationFactory.As<I>();
public IObjectReference _As(Guid iid) => _IActivationFactory.As<WinRT.Interop.IUnknownVftbl>(iid);
public ObjectReference<I> _As<I>() => Value.As<I>();
public IObjectReference _As(Guid iid) => Value.As<WinRT.Interop.IUnknownVftbl>(iid);
}

internal sealed class ActivationFactory<T> : BaseActivationFactory
Expand All @@ -621,51 +607,45 @@ public static ObjectReference<I> ActivateInstance<
#if NET
internal class BaseFactory
{
private volatile IObjectReference _factory;

private Tuple<IObjectReference, IntPtr> _factory;
public IObjectReference Value
#else
internal class BaseFactory<I>
{
private volatile ObjectReference<I> _factory;
private Tuple<ObjectReference<I>, IntPtr> _factory;
public ObjectReference<I> Value
#endif
{
{
get
{
var existingInstance = _factory;
if (existingInstance != null && (_contextToken == IntPtr.Zero || _contextToken == Context.GetContextToken()))
if (existingInstance.Item1 != null && (existingInstance.Item2 == IntPtr.Zero || existingInstance.Item2 == Context.GetContextToken()))
{
return existingInstance;
return existingInstance.Item1;
}

(var newFactory, var newToken) = InitializeFactory();
if (Interlocked.CompareExchange(ref _factory, newFactory, existingInstance) == existingInstance)
{
_contextToken = newToken;
}
return newFactory;
var newFactory = InitializeFactory();
Interlocked.CompareExchange(ref _factory, newFactory, existingInstance);
return newFactory.Item1;
}
}

private readonly string namespaceName;
private readonly string typeName;
private readonly Guid interfaceGuid;

private IntPtr _contextToken;
private readonly Guid interfaceGuid;

public BaseFactory(string namespaceName, string typeName, Guid interfaceGuid)
{
this.namespaceName = namespaceName;
this.typeName = typeName;
this.interfaceGuid = interfaceGuid;

(this._factory, this._contextToken) = InitializeFactory();
}

#if NET
private (IObjectReference, IntPtr) InitializeFactory()
private Tuple<IObjectReference, IntPtr> InitializeFactory()
#else
private (ObjectReference<I>, IntPtr) InitializeFactory()
private Tuple<IObjectReference, IntPtr> InitializeFactory()
#endif
{
// Prefer the RoGetActivationFactory HRESULT failure over the LoadLibrary/etc. failure
Expand All @@ -676,11 +656,11 @@ public BaseFactory(string namespaceName, string typeName, Guid interfaceGuid)
{
#if NET
var newContextToken = Context.IsFreeThreaded(factory) ? IntPtr.Zero : Context.GetContextToken();
return (factory, newContextToken);
return Tuple.Create(factory, newContextToken);
#else
var newFactory = factory.As<I>(interfaceGuid);
var newContextToken = Context.IsFreeThreaded(newFactory) ? IntPtr.Zero : Context.GetContextToken();
return (newFactory, newContextToken);
return Tuple.Create(newFactory, newContextToken);
#endif
}

Expand All @@ -699,7 +679,7 @@ public BaseFactory(string namespaceName, string typeName, Guid interfaceGuid)
var newFactory = factory.As<I>(interfaceGuid);
#endif
var newContextToken = Context.IsFreeThreaded(newFactory) ? IntPtr.Zero : Context.GetContextToken();
return (newFactory, newContextToken);
return Tuple.Create(newFactory, newContextToken);
}
}

Expand Down

0 comments on commit 73d5e29

Please sign in to comment.