factoring out Freeze/Unfreeze

This commit is contained in:
Christian Köllner 2020-04-06 21:12:08 +02:00
parent be10b356aa
commit e3b6fd5c62
11 changed files with 73 additions and 256 deletions

View File

@ -16,8 +16,7 @@ namespace Capnp.Rpc
/// </summary>
protected abstract void ReleaseRemotely();
internal abstract Action? Export(IRpcEndpoint endpoint, CapDescriptor.WRITER writer);
internal abstract void Freeze(out IRpcEndpoint? boundEndpoint);
internal abstract void Unfreeze();
internal abstract IRpcEndpoint? Endpoint { get; }
internal abstract void AddRef();
internal abstract void Release();

View File

@ -28,14 +28,7 @@ namespace Capnp.Rpc
return call;
}
internal override void Freeze(out IRpcEndpoint boundEndpoint)
{
boundEndpoint = _ep;
}
internal override void Unfreeze()
{
}
internal override IRpcEndpoint? Endpoint => _ep;
internal override Action? Export(IRpcEndpoint endpoint, CapDescriptor.WRITER capDesc)
{

View File

@ -35,13 +35,6 @@ namespace Capnp.Rpc.Interception
return null;
}
internal override void Freeze(out IRpcEndpoint? boundEndpoint)
{
boundEndpoint = null;
}
internal override void Unfreeze()
{
}
internal override IRpcEndpoint? Endpoint => null;
}
}

View File

@ -33,30 +33,7 @@ namespace Capnp.Rpc
_capTask = AwaitCap();
}
internal override void Freeze(out IRpcEndpoint? boundEndpoint)
{
if (WhenResolved.IsCompleted)
{
boundEndpoint = null;
try
{
_capTask.Result?.Freeze(out boundEndpoint);
}
catch (AggregateException exception)
{
throw exception.InnerException!;
}
}
else
{
boundEndpoint = null;
}
}
internal override void Unfreeze()
{
}
internal override IRpcEndpoint? Endpoint => null;
internal override Action? Export(IRpcEndpoint endpoint, CapDescriptor.WRITER writer)
{

View File

@ -29,15 +29,7 @@ namespace Capnp.Rpc
}
internal override void Freeze(out IRpcEndpoint? boundEndpoint)
{
boundEndpoint = null;
}
internal override void Unfreeze()
{
}
internal override IRpcEndpoint? Endpoint => null;
public Task WhenResolved => _whenResolvedProxy;

View File

@ -52,14 +52,7 @@ namespace Capnp.Rpc
return null;
}
internal override void Freeze(out IRpcEndpoint? boundEndpoint)
{
boundEndpoint = null;
}
internal override void Unfreeze()
{
}
internal override IRpcEndpoint? Endpoint => null;
protected override void ReleaseRemotely()
{

View File

@ -23,61 +23,7 @@ namespace Capnp.Rpc
public override Task WhenResolved => _resolvedCap.Task;
public override T? GetResolvedCapability<T>() where T: class => _whenResolvedProxy.GetResolvedCapability<T>();
internal override void Freeze(out IRpcEndpoint? boundEndpoint)
{
lock (_reentrancyBlocker)
{
if (_resolvedCap.Task.IsCompleted && _pendingCallsOnPromise == 0)
{
boundEndpoint = null;
try
{
_resolvedCap.Task.Result?.Freeze(out boundEndpoint);
}
catch (AggregateException exception)
{
throw exception.InnerException!;
}
}
else
{
Debug.Assert(!_released);
++_pendingCallsOnPromise;
boundEndpoint = _ep;
}
}
}
internal override void Unfreeze()
{
bool release = false;
lock (_reentrancyBlocker)
{
if (_pendingCallsOnPromise == 0)
{
_resolvedCap.Task.Result?.Unfreeze();
}
else
{
Debug.Assert(_pendingCallsOnPromise > 0);
Debug.Assert(!_released);
if (--_pendingCallsOnPromise == 0 && _resolvedCap.Task.IsCompleted)
{
release = true;
_released = true;
}
}
}
if (release)
{
_ep.ReleaseImport(_remoteId);
}
}
internal override IRpcEndpoint? Endpoint => _ep;
internal override Action? Export(IRpcEndpoint endpoint, CapDescriptor.WRITER writer)
{

View File

@ -238,23 +238,6 @@ namespace Capnp.Rpc
}
}
internal void Freeze(out IRpcEndpoint? boundEndpoint)
{
if (_disposedValue)
throw new ObjectDisposedException(nameof(Proxy));
boundEndpoint = null;
ConsumedCap?.Freeze(out boundEndpoint);
}
internal void Unfreeze()
{
if (_disposedValue)
throw new ObjectDisposedException(nameof(Proxy));
ConsumedCap?.Unfreeze();
}
#if DebugFinalizers
string CreatorStackTrace { get; set; }
#endif

View File

@ -174,45 +174,7 @@ namespace Capnp.Rpc
return call;
}
internal override void Freeze(out IRpcEndpoint? boundEndpoint)
{
lock (_question.ReentrancyBlocker)
{
if ( _question.StateFlags.HasFlag(PendingQuestion.State.Returned) &&
!_question.StateFlags.HasFlag(PendingQuestion.State.TailCall) &&
_pendingCallsOnPromise == 0)
{
if (ResolvedCap == null)
{
throw new RpcException("Answer did not resolve to expected capability");
}
ResolvedCap.Freeze(out boundEndpoint);
}
else
{
++_pendingCallsOnPromise;
_question.DisallowFinish();
boundEndpoint = _ep;
}
}
}
internal override void Unfreeze()
{
lock (_question.ReentrancyBlocker)
{
if (_pendingCallsOnPromise > 0)
{
--_pendingCallsOnPromise;
_question.AllowFinish();
}
else
{
ResolvedCap?.Unfreeze();
}
}
}
internal override IRpcEndpoint Endpoint => _ep;
internal override Action? Export(IRpcEndpoint endpoint, CapDescriptor.WRITER writer)
{

View File

@ -37,21 +37,13 @@ namespace Capnp.Rpc
try
{
ResolvedCap.Freeze(out var resolvedCapEndpoint);
try
{
if (resolvedCapEndpoint != null && resolvedCapEndpoint != _ep)
if (ResolvedCap.Endpoint!= null && ResolvedCap.Endpoint != _ep)
{
// Carol lives in a different Vat C.
throw new NotImplementedException("Sorry, level 3 RPC is not yet supported.");
}
if (ResolvedCap == null ||
// If the capability resolves to null, disembargo must not be requested.
// Take the direct path, well-knowing that the call will result in an exception.
resolvedCapEndpoint != null ||
if (ResolvedCap.Endpoint != null ||
//# Note that in the case where Carol actually lives in Vat B (i.e., the same vat that the promise
//# already pointed at), no embargo is needed, because the pipelined calls are delivered over the
//# same path as the later direct calls.
@ -119,11 +111,6 @@ namespace Capnp.Rpc
return new LocalAnswer(cancellationTokenSource, AwaitAnswer());
}
}
finally
{
ResolvedCap.Unfreeze();
}
}
catch (System.Exception exception)
{
// Wrap exception into local answer, since otherwise we'd get an AggregateException (which we don't want).

View File

@ -890,11 +890,8 @@ namespace Capnp.Rpc
try
{
using var proxy = await t;
proxy.Freeze(out var boundEndpoint);
try
{
if (boundEndpoint == this)
if (proxy.ConsumedCap?.Endpoint == this)
{
#if DebugEmbargos
Logger.LogDebug($"Sender loopback disembargo. Thread = {Thread.CurrentThread.Name}");
@ -908,11 +905,6 @@ namespace Capnp.Rpc
throw new RpcProtocolErrorException("'Disembargo': Answer does not resolve back to me");
}
}
finally
{
proxy.Unfreeze();
}
}
catch (System.Exception exception)
{
Logger.LogWarning($"Sender loopback request: Peer asked for disembargoing an answer which either has not yet returned, was canceled, or faulted: {exception.Message}");