Revert "resolve PromiseClient requests in order"

This reverts commit d526eca4b9.
This commit is contained in:
Vaci Koblizek 2020-11-17 14:32:37 +00:00
parent 3513db0588
commit 054e4efdb1

View file

@ -1509,33 +1509,43 @@ final class RpcState<VatId> {
private class RpcPipeline implements PipelineHook { private class RpcPipeline implements PipelineHook {
private final QuestionRef questionRef; private final QuestionRef questionRef;
private PipelineState state = PipelineState.WAITING;
private RpcResponse resolved;
private Throwable broken;
final HashMap<List<PipelineOp>, ClientHook> clientMap = new HashMap<>(); final HashMap<List<PipelineOp>, ClientHook> clientMap = new HashMap<>();
final CompletableFuture<RpcResponse> redirectLater; final CompletableFuture<RpcResponse> redirectLater;
final CompletableFuture<java.lang.Void> resolveSelf;
RpcPipeline(QuestionRef questionRef, RpcPipeline(QuestionRef questionRef,
CompletableFuture<RpcResponse> redirectLater) { CompletableFuture<RpcResponse> redirectLater) {
this.questionRef = questionRef; this.questionRef = questionRef;
assert redirectLater != null; assert redirectLater != null;
this.redirectLater = redirectLater; this.redirectLater = redirectLater;
this.resolveSelf = this.redirectLater
.thenAccept(response -> {
this.state = PipelineState.RESOLVED;
this.resolved = response;
})
.exceptionally(exc -> {
this.state = PipelineState.BROKEN;
this.broken = exc;
return null;
});
} }
RpcPipeline(QuestionRef questionRef) { RpcPipeline(QuestionRef questionRef) {
this(questionRef, null); this(questionRef, null);
// never resolves
} }
@Override @Override
public ClientHook getPipelinedCap(PipelineOp[] ops) { public ClientHook getPipelinedCap(PipelineOp[] ops) {
// We differ from the C++ implementation here.
// Previously, we would just store and return the resolved client, but this
// could cause tail calls to execute out of order.
// So instead we always chain resolution on the redirectLater promise, which
// ensures that each call initiated from this PromiseClient is executed in order.
// TODO avoid conversion to/from ArrayList? // TODO avoid conversion to/from ArrayList?
var key = new ArrayList<>(Arrays.asList(ops)); var key = new ArrayList<>(Arrays.asList(ops));
return this.clientMap.computeIfAbsent(key, k -> {
var hook = this.clientMap.computeIfAbsent(key, k -> {
switch (state) {
case WAITING: {
var pipelineClient = new PipelineClient(this.questionRef, ops); var pipelineClient = new PipelineClient(this.questionRef, ops);
if (this.redirectLater == null) { if (this.redirectLater == null) {
// This pipeline will never get redirected, so just return the PipelineClient. // This pipeline will never get redirected, so just return the PipelineClient.
@ -1545,7 +1555,16 @@ final class RpcState<VatId> {
var resolutionPromise = this.redirectLater.thenApply( var resolutionPromise = this.redirectLater.thenApply(
response -> response.getResults().getPipelinedCap(ops)); response -> response.getResults().getPipelinedCap(ops));
return new PromiseClient(pipelineClient, resolutionPromise, null); return new PromiseClient(pipelineClient, resolutionPromise, null);
}
case RESOLVED:
return resolved.getResults().getPipelinedCap(ops);
default:
return Capability.newBrokenCap(broken);
}
}); });
return hook;
} }
@Override @Override