2020-03-21 13:27:46 +01:00

83 lines
2.3 KiB
C#

using Microsoft.Extensions.Logging;
using System;
using System.Threading;
using System.Threading.Tasks;
namespace Capnp.Rpc
{
class Vine : Skeleton
{
public static Skeleton Create(ConsumedCapability cap)
{
if (cap is LocalCapability lcap)
return lcap.ProvidedCap;
else
return new Vine(cap);
}
Vine(ConsumedCapability consumedCap)
{
Proxy = new Proxy(consumedCap ?? throw new ArgumentNullException(nameof(consumedCap)));
#if DebugFinalizers
CreatorStackTrace = Environment.StackTrace;
#endif
}
#if DebugFinalizers
~Vine()
{
Logger.LogWarning($"Caught orphaned Vine, created from here: {CreatorStackTrace}.");
Dispose(false);
}
ILogger Logger { get; } = Logging.CreateLogger<Vine>();
string CreatorStackTrace { get; }
#endif
internal override void Bind(object impl)
{
throw new NotImplementedException();
}
public Proxy Proxy { get; }
public async override Task<AnswerOrCounterquestion> Invoke(
ulong interfaceId, ushort methodId, DeserializerState args,
CancellationToken cancellationToken = default)
{
var promisedAnswer = Proxy.Call(interfaceId, methodId, (DynamicSerializerState)args, default);
if (promisedAnswer is PendingQuestion pendingQuestion && pendingQuestion.RpcEndpoint == Impatient.AskingEndpoint)
{
async void SetupCancellation()
{
try
{
using var registration = cancellationToken.Register(promisedAnswer.Dispose);
await promisedAnswer.WhenReturned;
}
catch
{
}
}
SetupCancellation();
return pendingQuestion;
}
else
{
using var registration = cancellationToken.Register(promisedAnswer.Dispose);
return (DynamicSerializerState)await promisedAnswer.WhenReturned;
}
}
protected override void Dispose(bool disposing)
{
Proxy.Dispose();
base.Dispose(disposing);
}
}
}