89 lines
2.8 KiB
C#
Raw Normal View History

using Capnp.Util;
using System;
2019-06-12 21:56:55 +02:00
using System.Threading;
using System.Threading.Tasks;
namespace Capnp.Rpc
{
2020-03-10 21:55:34 +01:00
2019-06-12 21:56:55 +02:00
class LocalAnswerCapability : RefCountingCapability, IResolvingCapability
{
static async Task<Proxy> TransferOwnershipToDummyProxy(StrictlyOrderedAwaitTask<DeserializerState> answer, MemberAccessPath access)
2020-03-22 00:12:50 +01:00
{
var result = await answer;
var cap = access.Eval(result);
var proxy = new Proxy(cap);
cap?.Release();
2020-03-22 00:12:50 +01:00
return proxy;
}
readonly StrictlyOrderedAwaitTask<Proxy> _whenResolvedProxy;
2019-06-12 21:56:55 +02:00
2020-03-10 21:55:34 +01:00
public LocalAnswerCapability(Task<Proxy> proxyTask)
2019-06-12 21:56:55 +02:00
{
_whenResolvedProxy = proxyTask.EnforceAwaitOrder();
2019-06-12 21:56:55 +02:00
}
public LocalAnswerCapability(StrictlyOrderedAwaitTask<DeserializerState> answer, MemberAccessPath access):
2020-03-22 00:12:50 +01:00
this(TransferOwnershipToDummyProxy(answer, access))
{
}
public StrictlyOrderedAwaitTask WhenResolved => _whenResolvedProxy;
public T? GetResolvedCapability<T>() where T : class => _whenResolvedProxy.WrappedTask.GetResolvedCapability<T>();
2019-06-12 21:56:55 +02:00
internal override Action? Export(IRpcEndpoint endpoint, CapDescriptor.WRITER writer)
2019-06-12 21:56:55 +02:00
{
2020-03-10 21:55:34 +01:00
if (_whenResolvedProxy.IsCompleted)
2019-06-12 21:56:55 +02:00
{
try
{
2020-03-10 21:55:34 +01:00
_whenResolvedProxy.Result.Export(endpoint, writer);
2019-06-12 21:56:55 +02:00
}
catch (AggregateException exception)
{
throw exception.InnerException!;
2019-06-12 21:56:55 +02:00
}
return null;
2019-06-12 21:56:55 +02:00
}
else
{
return this.ExportAsSenderPromise(endpoint, writer);
2019-06-12 21:56:55 +02:00
}
}
async Task<DeserializerState> CallImpl(ulong interfaceId, ushort methodId, DynamicSerializerState args, CancellationToken cancellationToken)
2019-06-12 21:56:55 +02:00
{
2020-03-10 21:55:34 +01:00
var proxy = await _whenResolvedProxy;
2019-06-12 21:56:55 +02:00
cancellationToken.ThrowIfCancellationRequested();
2020-03-10 21:55:34 +01:00
if (proxy.IsNull)
2020-03-22 13:57:02 +01:00
{
args.Dispose();
2019-06-12 21:56:55 +02:00
throw new RpcException("Broken capability");
2020-03-22 13:57:02 +01:00
}
2019-06-12 21:56:55 +02:00
2020-03-10 21:55:34 +01:00
var call = proxy.Call(interfaceId, methodId, args, default);
2019-06-12 21:56:55 +02:00
var whenReturned = call.WhenReturned;
2020-03-10 21:55:34 +01:00
using var registration = cancellationToken.Register(() => call.Dispose());
return await whenReturned;
2019-06-12 21:56:55 +02:00
}
internal override IPromisedAnswer DoCall(ulong interfaceId, ushort methodId, DynamicSerializerState args)
2019-06-12 21:56:55 +02:00
{
var cts = new CancellationTokenSource();
return new LocalAnswer(cts, CallImpl(interfaceId, methodId, args, cts.Token));
2019-06-12 21:56:55 +02:00
}
2020-03-10 21:55:34 +01:00
protected async override void ReleaseRemotely()
2019-06-12 21:56:55 +02:00
{
2020-03-10 21:55:34 +01:00
try { using var _ = await _whenResolvedProxy; }
catch { }
2019-06-12 21:56:55 +02:00
}
}
2020-01-11 17:56:12 +01:00
}