internal override void Export(IRpcEndpoint endpoint, CapDescriptor.WRITER capDesc) { if (endpoint == _ep) { capDesc.which = CapDescriptor.WHICH.ReceiverHosted; capDesc.ReceiverHosted = _remoteId; } else { capDesc.which = CapDescriptor.WHICH.SenderHosted; capDesc.SenderHosted = endpoint.AllocateExport(Vine.Create(this), out var _); } }
internal IProvidedCapability GetProvider() { switch (ConsumedCap) { case LocalCapability lcap: return(lcap.ProvidedCap); case null: return(null); default: return(Vine.Create(ConsumedCap)); } }
internal override void Export(IRpcEndpoint endpoint, CapDescriptor.WRITER writer) { lock (_question.ReentrancyBlocker) { if (_question.StateFlags.HasFlag(PendingQuestion.State.Disposed)) { throw new ObjectDisposedException(nameof(PendingQuestion)); } if (_question.StateFlags.HasFlag(PendingQuestion.State.Returned)) { ResolvedCap.Export(endpoint, writer); } else { if (_question.StateFlags.HasFlag(PendingQuestion.State.FinishRequested)) { throw new InvalidOperationException("Finish request was already sent"); } if (endpoint == _ep) { writer.which = CapDescriptor.WHICH.ReceiverAnswer; _access.Serialize(writer.ReceiverAnswer); writer.ReceiverAnswer.QuestionId = _question.QuestionId; } else if (_question.IsTailCall) { // FIXME: Resource management! We should prevent finishing this // cap as long as it is exported. Unfortunately, we cannot determine // when it gets removed from the export table. var vine = Vine.Create(this); uint id = endpoint.AllocateExport(vine, out bool first); writer.which = CapDescriptor.WHICH.SenderHosted; writer.SenderHosted = id; } else { this.ExportAsSenderPromise(endpoint, writer); } } } }