76 lines
2.4 KiB
C#
Raw Normal View History

2019-06-12 21:56:55 +02:00
using System;
using System.Runtime.CompilerServices;
using System.Threading;
using System.Threading.Tasks;
namespace Capnp.Rpc
{
class LocalCapability : ConsumedCapability
{
public static ConsumedCapability Create(Skeleton skeleton)
{
if (skeleton is Vine vine)
2020-01-11 17:21:31 +01:00
return vine.Proxy.ConsumedCap!;
2019-06-12 21:56:55 +02:00
else
2020-03-10 21:55:34 +01:00
return new LocalCapability(skeleton);
2019-06-12 21:56:55 +02:00
}
static async Task<DeserializerState> AwaitAnswer(Task<AnswerOrCounterquestion> call)
{
var aorcq = await call;
2020-01-11 17:21:31 +01:00
return aorcq.Answer ?? await aorcq.Counterquestion!.WhenReturned;
2019-06-12 21:56:55 +02:00
}
public Skeleton ProvidedCap { get; }
2020-03-10 21:55:34 +01:00
int _releaseFlag;
2019-06-12 21:56:55 +02:00
LocalCapability(Skeleton providedCap)
{
ProvidedCap = providedCap ?? throw new ArgumentNullException(nameof(providedCap));
}
internal override void AddRef()
{
2020-03-10 21:55:34 +01:00
if (0 == Interlocked.CompareExchange(ref _releaseFlag, 0, 1))
ProvidedCap.Claim();
2019-06-12 21:56:55 +02:00
}
internal override void Release(
2020-03-10 21:55:34 +01:00
bool keepAlive,
[System.Runtime.CompilerServices.CallerMemberName] string methodName = "",
[System.Runtime.CompilerServices.CallerFilePath] string filePath = "",
[System.Runtime.CompilerServices.CallerLineNumber] int lineNumber = 0)
2019-06-12 21:56:55 +02:00
{
2020-03-10 21:55:34 +01:00
if (keepAlive)
Interlocked.Exchange(ref _releaseFlag, 1);
else
ProvidedCap.Relinquish();
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();
var call = ProvidedCap.Invoke(interfaceId, methodId, args, cts.Token);
return new LocalAnswer(cts, AwaitAnswer(call));
}
internal override void Export(IRpcEndpoint endpoint, CapDescriptor.WRITER capDesc)
{
capDesc.which = CapDescriptor.WHICH.SenderHosted;
capDesc.SenderHosted = endpoint.AllocateExport(ProvidedCap, out bool _);
}
2020-01-11 17:21:31 +01:00
internal override void Freeze(out IRpcEndpoint? boundEndpoint)
2019-06-12 21:56:55 +02:00
{
boundEndpoint = null;
}
internal override void Unfreeze()
{
}
protected override void ReleaseRemotely()
{
}
}
2020-01-11 17:56:12 +01:00
}