Files
Benchmarking
Capnp.Net.Runtime
FrameTracing
Rpc
Interception
AnswerOrCounterquestion.cs
BareProxy.cs
CapabilityReflection.cs
ConnectionState.cs
ConsumedCapability.cs
IConnection.cs
IEndpoint.cs
IMonoSkeleton.cs
IPromisedAnswer.cs
IProvidedCapability.cs
IResolvingCapability.cs
IRpcEndpoint.cs
ISupportsMidlayers.cs
Impatient.cs
ImportedCapability.cs
InvalidCapabilityInterfaceException.cs
LazyCapability.cs
LocalAnswer.cs
LocalAnswerCapability.cs
LocalCapability.cs
MemberAccessPath.cs
MidlayerExtensions.cs
NoResultsException.cs
NullCapability.cs
NullSkeleton.cs
PendingAnswer.cs
PendingQuestion.cs
PolySkeleton.cs
PromisedCapability.cs
Proxy.cs
ProxyAttribute.cs
RefCountingCapability.cs
RefCountingSkeleton.cs
RemoteAnswerCapability.cs
RemoteCapability.cs
RemoteResolvingCapability.cs
ResolvingCapabilityExtensions.cs
RpcEngine.cs
RpcException.cs
RpcProtocolErrorException.cs
RpcUnimplementedException.cs
Skeleton.cs
SkeletonAttribute.cs
TcpRpcClient.cs
TcpRpcServer.cs
Vine.cs
rpc.cs
Util
AnyPointer.cs
Assembly.cs
Capnp.Net.Runtime.Std20.xml
Capnp.Net.Runtime.csproj
CapnpSerializable.cs
DeserializationException.cs
DeserializerState.cs
DynamicSerializerState.cs
EmptyList.cs
EmptyListDeserializer.cs
FramePump.cs
Framing.cs
ICapnpSerializable.cs
ISegmentAllocator.cs
IStructDeserializer.cs
IStructSerializer.cs
ListDeserializer.cs
ListKind.cs
ListOfBitsDeserializer.cs
ListOfBitsSerializer.cs
ListOfCapsDeserializer.cs
ListOfCapsSerializer.cs
ListOfEmptyDeserializer.cs
ListOfEmptySerializer.cs
ListOfPointersDeserializer.cs
ListOfPointersSerializer.cs
ListOfPrimitivesDeserializer.cs
ListOfPrimitivesSerializer.cs
ListOfStructsDeserializer.cs
ListOfStructsSerializer.cs
ListOfTextSerializer.cs
ListSerializerHelper.cs
Logging.cs
MessageBuilder.cs
NullableAttributes.cs
ObjectKind.cs
ReadOnlyListExtensions.cs
Reserializing.cs
SecurityOptions.cs
SegmentAllocator.cs
SegmentSlice.cs
SerializerExtensions.cs
SerializerState.cs
TypeIdAttribute.cs
UtilityExtensions.cs
WireFrame.cs
WirePointer.cs
Capnp.Net.Runtime.Tests
CapnpC.CSharp.Generator
CapnpC.CSharp.Generator.Tests
CapnpC.CSharp.MsBuild.Generation
CapnpC.CSharp.MsBuild.Generation.Tests
CapnpCompatTest
Licenses
MsBuildGenerationTest
capnpc-csharp
chocolatey
include
install-test
scripts
.gitattributes
.gitignore
Capnp.Net.sln
CapnpCompatTest.sln
Directory.Build.props
Directory.Build.targets
LICENSE
README.md
appveyor.yml
coverlet.runsettings
version.json
libs.capnproto-dotnetcore_R…/Capnp.Net.Runtime/Rpc/LazyCapability.cs
2020-04-23 22:34:45 +02:00

121 lines
3.7 KiB
C#

using Capnp.Util;
using System;
using System.Threading;
using System.Threading.Tasks;
namespace Capnp.Rpc
{
class LazyCapability : RefCountingCapability, IResolvingCapability
{
public static LazyCapability CreateBrokenCap(string message)
{
return new LazyCapability(Task.FromException<ConsumedCapability>(new RpcException(message)));
}
public static LazyCapability CreateCanceledCap(CancellationToken token)
{
return new LazyCapability(Task.FromCanceled<ConsumedCapability>(token));
}
readonly StrictlyOrderedAwaitTask<Proxy>? _proxyTask;
readonly StrictlyOrderedAwaitTask<ConsumedCapability> _capTask;
public LazyCapability(Task<ConsumedCapability> capabilityTask)
{
_capTask = capabilityTask.EnforceAwaitOrder();
}
public LazyCapability(Task<Proxy> proxyTask)
{
_proxyTask = proxyTask.EnforceAwaitOrder();
async Task<ConsumedCapability> AwaitCap() => (await _proxyTask!).ConsumedCap;
_capTask = AwaitCap().EnforceAwaitOrder();
}
internal override Action? Export(IRpcEndpoint endpoint, CapDescriptor.WRITER writer)
{
if (WhenResolved.IsCompleted && WhenResolved.WrappedTask.ReplacementTaskIsCompletedSuccessfully())
{
using var proxy = GetResolvedCapability<BareProxy>()!;
return proxy.Export(endpoint, writer);
}
else
{
return this.ExportAsSenderPromise(endpoint, writer);
}
}
protected override void ReleaseRemotely()
{
if (_proxyTask != null)
{
async void DisposeProxyWhenResolved()
{
try { using var _ = await _proxyTask!; }
catch { }
}
DisposeProxyWhenResolved();
}
}
public StrictlyOrderedAwaitTask WhenResolved => _capTask;
public T? GetResolvedCapability<T>() where T: class
{
if (_capTask.WrappedTask.IsCompleted)
{
try
{
return (CapabilityReflection.CreateProxy<T>(_capTask.Result) as T)!;
}
catch (AggregateException exception)
{
throw exception.InnerException!;
}
}
else
{
return null;
}
}
async Task<DeserializerState> CallImpl(ulong interfaceId, ushort methodId, DynamicSerializerState args, CancellationToken cancellationToken)
{
ConsumedCapability cap;
try
{
cap = await _capTask;
}
catch
{
args.Dispose();
throw;
}
if (cancellationToken.IsCancellationRequested)
{
args.Dispose();
cancellationToken.ThrowIfCancellationRequested();
}
using var proxy = new Proxy(cap);
var call = proxy.Call(interfaceId, methodId, args, default);
var whenReturned = call.WhenReturned;
using (var registration = cancellationToken.Register(call.Dispose))
{
return await whenReturned;
}
}
internal override IPromisedAnswer DoCall(ulong interfaceId, ushort methodId, DynamicSerializerState args)
{
var cts = new CancellationTokenSource();
return new LocalAnswer(cts, CallImpl(interfaceId, methodId, args, cts.Token));
}
}
}