From d7f937a9c013c6cdb2ef8dde96d65348a2b61d42 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6llner?= Date: Fri, 3 Apr 2020 22:10:40 +0200 Subject: [PATCH] refactored IResolvingCapability to hide ConsumedCapability --- Capnp.Net.Runtime/Rpc/IResolvingCapability.cs | 11 +++++-- Capnp.Net.Runtime/Rpc/LazyCapability.cs | 32 +++++++++++++++---- .../Rpc/LocalAnswerCapability.cs | 7 ++-- Capnp.Net.Runtime/Rpc/PromisedCapability.cs | 5 +-- Capnp.Net.Runtime/Rpc/Proxy.cs | 24 ++++++++++---- .../Rpc/RemoteAnswerCapability.cs | 18 +++-------- .../Rpc/RemoteResolvingCapability.cs | 3 +- .../Rpc/ResolvingCapabilityExtensions.cs | 27 ++++++++++++++-- 8 files changed, 90 insertions(+), 37 deletions(-) diff --git a/Capnp.Net.Runtime/Rpc/IResolvingCapability.cs b/Capnp.Net.Runtime/Rpc/IResolvingCapability.cs index cc26602..b3dc986 100644 --- a/Capnp.Net.Runtime/Rpc/IResolvingCapability.cs +++ b/Capnp.Net.Runtime/Rpc/IResolvingCapability.cs @@ -8,8 +8,15 @@ namespace Capnp.Rpc public interface IResolvingCapability { /// - /// Will eventually give the resolved capability. + /// Completes when the capability gets resolved. /// - Task WhenResolved { get; } + Task WhenResolved { get; } + + /// + /// Returns the resolved capability + /// + /// Capability interface or + /// the resolved capability, or null if it did not resolve yet + T? GetResolvedCapability() where T: class; } } \ No newline at end of file diff --git a/Capnp.Net.Runtime/Rpc/LazyCapability.cs b/Capnp.Net.Runtime/Rpc/LazyCapability.cs index 880b837..3e11953 100644 --- a/Capnp.Net.Runtime/Rpc/LazyCapability.cs +++ b/Capnp.Net.Runtime/Rpc/LazyCapability.cs @@ -17,10 +17,11 @@ namespace Capnp.Rpc } readonly Task? _proxyTask; + readonly Task _capTask; public LazyCapability(Task capabilityTask) { - WhenResolved = capabilityTask; + _capTask = capabilityTask; } public LazyCapability(Task proxyTask) @@ -29,7 +30,7 @@ namespace Capnp.Rpc async Task AwaitCap() => (await _proxyTask!).ConsumedCap; - WhenResolved = AwaitCap(); + _capTask = AwaitCap(); } internal override void Freeze(out IRpcEndpoint? boundEndpoint) @@ -40,7 +41,7 @@ namespace Capnp.Rpc try { - WhenResolved.Result?.Freeze(out boundEndpoint); + _capTask.Result?.Freeze(out boundEndpoint); } catch (AggregateException exception) { @@ -61,7 +62,7 @@ namespace Capnp.Rpc { if (WhenResolved.ReplacementTaskIsCompletedSuccessfully()) { - using var proxy = new Proxy(WhenResolved.Result); + using var proxy = GetResolvedCapability()!; return proxy.Export(endpoint, writer); } else @@ -84,14 +85,33 @@ namespace Capnp.Rpc } } - public Task WhenResolved { get; } + public Task WhenResolved => _capTask; + + public T? GetResolvedCapability() where T: class + { + if (_capTask.IsCompleted) + { + try + { + return CapabilityReflection.CreateProxy(_capTask.Result) as T; + } + catch (AggregateException exception) + { + throw exception.InnerException!; + } + } + else + { + return null; + } + } async Task CallImpl(ulong interfaceId, ushort methodId, DynamicSerializerState args, CancellationToken cancellationToken) { ConsumedCapability? cap; try { - cap = await WhenResolved; + cap = await _capTask; } catch { diff --git a/Capnp.Net.Runtime/Rpc/LocalAnswerCapability.cs b/Capnp.Net.Runtime/Rpc/LocalAnswerCapability.cs index 08a5437..e29a1b3 100644 --- a/Capnp.Net.Runtime/Rpc/LocalAnswerCapability.cs +++ b/Capnp.Net.Runtime/Rpc/LocalAnswerCapability.cs @@ -21,9 +21,6 @@ namespace Capnp.Rpc public LocalAnswerCapability(Task proxyTask) { _whenResolvedProxy = proxyTask; - - async Task AwaitResolved() => (await _whenResolvedProxy).ConsumedCap; - WhenResolved = AwaitResolved(); } public LocalAnswerCapability(Task answer, MemberAccessPath access): @@ -42,7 +39,9 @@ namespace Capnp.Rpc } - public Task WhenResolved { get; private set; } + public Task WhenResolved => _whenResolvedProxy; + + public T? GetResolvedCapability() where T : class => _whenResolvedProxy.GetResolvedCapability(); internal override Action? Export(IRpcEndpoint endpoint, CapDescriptor.WRITER writer) { diff --git a/Capnp.Net.Runtime/Rpc/PromisedCapability.cs b/Capnp.Net.Runtime/Rpc/PromisedCapability.cs index 0099383..0b5bfbf 100644 --- a/Capnp.Net.Runtime/Rpc/PromisedCapability.cs +++ b/Capnp.Net.Runtime/Rpc/PromisedCapability.cs @@ -16,11 +16,12 @@ namespace Capnp.Rpc { _remoteId = remoteId; - async Task AwaitProxy() => new Proxy(await WhenResolved); + async Task AwaitProxy() => new Proxy(await _resolvedCap.Task); _whenResolvedProxy = AwaitProxy(); } - public override Task WhenResolved => _resolvedCap.Task; + public override Task WhenResolved => _resolvedCap.Task; + public override T? GetResolvedCapability() where T: class => _whenResolvedProxy.GetResolvedCapability(); internal override void Freeze(out IRpcEndpoint? boundEndpoint) { diff --git a/Capnp.Net.Runtime/Rpc/Proxy.cs b/Capnp.Net.Runtime/Rpc/Proxy.cs index 53ec1af..34f09c1 100644 --- a/Capnp.Net.Runtime/Rpc/Proxy.cs +++ b/Capnp.Net.Runtime/Rpc/Proxy.cs @@ -17,7 +17,7 @@ namespace Capnp.Rpc /// Capability interface /// instance to share /// - public static T Share(T obj) where T: class + public static T Share(T obj) where T : class { if (obj is Proxy proxy) return proxy.Cast(false); @@ -32,18 +32,30 @@ namespace Capnp.Rpc bool _disposedValue = false; /// - /// Will eventually give the resolved capability, if this is a promised capability. + /// Completes when the capability gets resolved. /// - public Task WhenResolved + public Task WhenResolved { get { - return ConsumedCap is IResolvingCapability resolving ? - resolving.WhenResolved : - Task.FromResult(ConsumedCap); + return ConsumedCap is IResolvingCapability resolving ? + resolving.WhenResolved : Task.CompletedTask; } } + /// + /// Returns the resolved capability + /// + /// Capability interface or + /// the resolved capability, or null if it did not resolve yet + public T? GetResolvedCapability() where T : class + { + if (ConsumedCap is IResolvingCapability resolving) + return resolving.GetResolvedCapability(); + else + return CapabilityReflection.CreateProxy(ConsumedCap) as T; + } + /// /// Underlying low-level capability /// diff --git a/Capnp.Net.Runtime/Rpc/RemoteAnswerCapability.cs b/Capnp.Net.Runtime/Rpc/RemoteAnswerCapability.cs index fd47935..734899b 100644 --- a/Capnp.Net.Runtime/Rpc/RemoteAnswerCapability.cs +++ b/Capnp.Net.Runtime/Rpc/RemoteAnswerCapability.cs @@ -23,18 +23,6 @@ namespace Capnp.Rpc _question = question ?? throw new ArgumentNullException(nameof(question)); _access = access ?? throw new ArgumentNullException(nameof(access)); _whenResolvedProxy = proxyTask ?? throw new ArgumentNullException(nameof(proxyTask)); - - async Task AwaitWhenResolved() - { - var proxy = await _whenResolvedProxy; - - if (_question.IsTailCall) - throw new InvalidOperationException("Question is a tail call, so won't resolve back."); - - return proxy.ConsumedCap; - } - - WhenResolved = AwaitWhenResolved(); } static async Task TransferOwnershipToDummyProxy(PendingQuestion question, MemberAccessPath access) @@ -81,7 +69,7 @@ namespace Capnp.Rpc { try { - return WhenResolved.Result; + return _whenResolvedProxy.Result.ConsumedCap; } catch (AggregateException exception) { @@ -96,7 +84,9 @@ namespace Capnp.Rpc } } - public override Task WhenResolved { get; } + public override Task WhenResolved => _whenResolvedProxy; + + public override T? GetResolvedCapability() where T: class => _whenResolvedProxy.GetResolvedCapability(); protected override void GetMessageTarget(MessageTarget.WRITER wr) { diff --git a/Capnp.Net.Runtime/Rpc/RemoteResolvingCapability.cs b/Capnp.Net.Runtime/Rpc/RemoteResolvingCapability.cs index b6a9cf8..6f3ba0b 100644 --- a/Capnp.Net.Runtime/Rpc/RemoteResolvingCapability.cs +++ b/Capnp.Net.Runtime/Rpc/RemoteResolvingCapability.cs @@ -16,7 +16,8 @@ namespace Capnp.Rpc ILogger Logger { get; } = Logging.CreateLogger(); #endif - public abstract Task WhenResolved { get; } + public abstract Task WhenResolved { get; } + public abstract T? GetResolvedCapability() where T : class; protected RemoteResolvingCapability(IRpcEndpoint ep) : base(ep) { diff --git a/Capnp.Net.Runtime/Rpc/ResolvingCapabilityExtensions.cs b/Capnp.Net.Runtime/Rpc/ResolvingCapabilityExtensions.cs index 23b3fab..7fae258 100644 --- a/Capnp.Net.Runtime/Rpc/ResolvingCapabilityExtensions.cs +++ b/Capnp.Net.Runtime/Rpc/ResolvingCapabilityExtensions.cs @@ -9,7 +9,9 @@ namespace Capnp.Rpc { while (cap is IResolvingCapability resolving) { - cap = await resolving.WhenResolved; + await resolving.WhenResolved; + using var proxy = resolving.GetResolvedCapability()!; + cap = proxy.ConsumedCap; } return cap; @@ -30,7 +32,9 @@ namespace Capnp.Rpc try { - var resolvedCap = await Unwrap(await cap.WhenResolved); + await cap.WhenResolved; + using var proxy = cap.GetResolvedCapability()!; + var resolvedCap = await Unwrap(proxy.ConsumedCap); endpoint.Resolve(preliminaryId, vine, () => resolvedCap!); } catch (System.Exception exception) @@ -68,5 +72,24 @@ namespace Capnp.Rpc default: return BareProxy.FromImpl(obj); } } + + public static T? GetResolvedCapability(this Task proxyTask) where T: class + { + if (proxyTask.IsCompleted) + { + try + { + return proxyTask.Result.Cast(false); + } + catch (AggregateException exception) + { + throw exception.InnerException!; + } + } + else + { + return null; + } + } } } \ No newline at end of file