diff --git a/Capnp.Net.Runtime.Tests/TcpRpcInterop.cs b/Capnp.Net.Runtime.Tests/TcpRpcInterop.cs index 5886456..7ad9852 100644 --- a/Capnp.Net.Runtime.Tests/TcpRpcInterop.cs +++ b/Capnp.Net.Runtime.Tests/TcpRpcInterop.cs @@ -1046,7 +1046,7 @@ namespace Capnp.Net.Runtime.Tests { LaunchCompatTestProcess("server:MoreStuff", stdout => { - for (int i = 0; i < 100; i++) + for (int i = 0; i < 20; i++) { EmbargoErrorImpl(stdout); } diff --git a/Capnp.Net.Runtime.Tests/TcpRpcStress.cs b/Capnp.Net.Runtime.Tests/TcpRpcStress.cs index 8f6eec1..7fb4590 100644 --- a/Capnp.Net.Runtime.Tests/TcpRpcStress.cs +++ b/Capnp.Net.Runtime.Tests/TcpRpcStress.cs @@ -67,7 +67,7 @@ namespace Capnp.Net.Runtime.Tests public void EmbargoServer() { var t2 = new TcpRpcInterop(); - Repeat(100, t2.EmbargoServer); + Repeat(20, t2.EmbargoServer); } [TestMethod] diff --git a/Capnp.Net.Runtime/Rpc/BareProxy.cs b/Capnp.Net.Runtime/Rpc/BareProxy.cs index ff68ab0..71c4dbe 100644 --- a/Capnp.Net.Runtime/Rpc/BareProxy.cs +++ b/Capnp.Net.Runtime/Rpc/BareProxy.cs @@ -19,7 +19,7 @@ /// Problem with building the Skeleton type, or problem with loading some dependent class. public static BareProxy FromImpl(object impl) { - return new BareProxy(CapabilityReflection.CreateSkeleton(impl).AsCapability()); + return new BareProxy(CapabilityReflection.CreateSkeletonInternal(impl).AsCapability()); } /// diff --git a/Capnp.Net.Runtime/Rpc/CapabilityReflection.cs b/Capnp.Net.Runtime/Rpc/CapabilityReflection.cs index 97b8b63..2512bda 100644 --- a/Capnp.Net.Runtime/Rpc/CapabilityReflection.cs +++ b/Capnp.Net.Runtime/Rpc/CapabilityReflection.cs @@ -94,6 +94,8 @@ namespace Capnp.Rpc new ConditionalWeakTable(); static ConditionalWeakTable _skeletonMap = new ConditionalWeakTable(); + static ConditionalWeakTable _implMap = + new ConditionalWeakTable(); static CapabilityReflection() { @@ -155,15 +157,23 @@ namespace Capnp.Rpc /// Problem with instatiating the Skeleton (constructor threw exception). /// Caller does not have permission to invoke the Skeleton constructor. /// Problem with building the Skeleton type, or problem with loading some dependent class. - public static Skeleton CreateSkeleton(object obj) + [Obsolete("Do not use this method directly. Instead, pass objects directly or use Proxy.Share(). This method will be removed with next release.")] + public static Skeleton CreateSkeleton(object obj) => CreateSkeletonInternal(obj); + + internal static Skeleton CreateSkeletonInternal(object obj) { if (obj == null) throw new ArgumentNullException(nameof(obj)); - var factory = GetSkeletonFactory(obj.GetType()); - var skeleton = factory.NewSkeleton(); - skeleton.Bind(obj); - return skeleton; + var result = _implMap.GetValue(obj, _ => + { + var factory = GetSkeletonFactory(_.GetType()); + var skeleton = factory.NewSkeleton(); + skeleton.Bind(obj); + return skeleton; + }); + + return result; } static ProxyFactory GetProxyFactory(Type type) diff --git a/Capnp.Net.Runtime/Rpc/Interception/CallContext.cs b/Capnp.Net.Runtime/Rpc/Interception/CallContext.cs index 9169022..3911fae 100644 --- a/Capnp.Net.Runtime/Rpc/Interception/CallContext.cs +++ b/Capnp.Net.Runtime/Rpc/Interception/CallContext.cs @@ -180,7 +180,7 @@ namespace Capnp.Rpc.Interception break; default: - Bob = Skeleton.GetOrCreateSkeleton(value, false); + Bob = CapabilityReflection.CreateSkeletonInternal(value); break; } diff --git a/Capnp.Net.Runtime/Rpc/Interception/Interceptor.cs b/Capnp.Net.Runtime/Rpc/Interception/Interceptor.cs index d2f241d..b951676 100644 --- a/Capnp.Net.Runtime/Rpc/Interception/Interceptor.cs +++ b/Capnp.Net.Runtime/Rpc/Interception/Interceptor.cs @@ -53,7 +53,7 @@ namespace Capnp.Rpc.Interception default: var temp = (CapabilityReflection.CreateProxy( - Skeleton.GetOrCreateSkeleton(cap, false).AsCapability())) as TCap; + CapabilityReflection.CreateSkeletonInternal(cap).AsCapability())) as TCap; return Attach(policy, temp!)!; } } diff --git a/Capnp.Net.Runtime/Rpc/RpcEngine.cs b/Capnp.Net.Runtime/Rpc/RpcEngine.cs index 3a32481..3a8b8ed 100644 --- a/Capnp.Net.Runtime/Rpc/RpcEngine.cs +++ b/Capnp.Net.Runtime/Rpc/RpcEngine.cs @@ -1570,7 +1570,7 @@ namespace Capnp.Rpc /// public object Main { - set { BootstrapCap = Skeleton.GetOrCreateSkeleton(value, false); } + set { BootstrapCap = value is Skeleton skeleton ? skeleton : CapabilityReflection.CreateSkeletonInternal(value); } } } } \ No newline at end of file diff --git a/Capnp.Net.Runtime/Rpc/Skeleton.cs b/Capnp.Net.Runtime/Rpc/Skeleton.cs index e6a0e83..f8ffaa0 100644 --- a/Capnp.Net.Runtime/Rpc/Skeleton.cs +++ b/Capnp.Net.Runtime/Rpc/Skeleton.cs @@ -18,6 +18,7 @@ namespace Capnp.Rpc public SkeletonRelinquisher(Skeleton skeleton) { _skeleton = skeleton; + _skeleton.Claim(); } public void Dispose() @@ -26,28 +27,6 @@ namespace Capnp.Rpc } } - static readonly ConditionalWeakTable _implMap = - new ConditionalWeakTable(); - - internal static Skeleton GetOrCreateSkeleton(T impl, bool addRef) - where T: class - { - if (impl == null) - throw new ArgumentNullException(nameof(impl)); - - if (impl is Skeleton skel) - return skel; - - skel = _implMap.GetValue(impl, _ => CapabilityReflection.CreateSkeleton(_)); - - if (addRef) - { - skel.Claim(); - } - - return skel; - } - /// /// Claims ownership on the given capability, preventing its automatic disposal. /// @@ -56,7 +35,7 @@ namespace Capnp.Rpc /// A disposable object. Calling Dispose() on the returned instance relinquishes ownership again. public static IDisposable Claim(T impl) where T: class { - return new SkeletonRelinquisher(GetOrCreateSkeleton(impl, true)); + return new SkeletonRelinquisher(CapabilityReflection.CreateSkeletonInternal(impl)); } /// diff --git a/Capnp.Net.Runtime/SerializerState.cs b/Capnp.Net.Runtime/SerializerState.cs index 30fc21e..39f7f80 100644 --- a/Capnp.Net.Runtime/SerializerState.cs +++ b/Capnp.Net.Runtime/SerializerState.cs @@ -1291,7 +1291,7 @@ namespace Capnp case Rpc.Skeleton providedCapability: return ProvideCapability(providedCapability); default: - return ProvideCapability(Rpc.Skeleton.GetOrCreateSkeleton(obj, false)); + return ProvideCapability(Rpc.CapabilityReflection.CreateSkeletonInternal(obj)); } }