Skip to content

Commit

Permalink
docs(swingset): Include promise forward constraints
Browse files Browse the repository at this point in the history
  • Loading branch information
mhofman committed Apr 25, 2022
1 parent 5eec3a0 commit 1b7cead
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 7 deletions.
3 changes: 2 additions & 1 deletion packages/SwingSet/docs/comms.md
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,8 @@ A send-with-result of two slots, `p = E(target).foo(1,2,bar,baz)`, would be

Promises that resolve to data, or which are rejected, will have a `body` and
possibly `slots`. Each slot can hold any kind of reference: `ro+NN`, `ro-NN`,
`rp+NN`, or `rp-NN`.
`rp+NN`, or `rp-NN`. A promise cannot currently be resolved directly to another
promise, unless the promise value is nested in data, or it's a rejection.

Promises that resolve to a callable object have a single `resolutionRef`,
which always resolves to `ro+NN` or `ro-NN`.
Expand Down
31 changes: 25 additions & 6 deletions packages/SwingSet/docs/delivery.md
Original file line number Diff line number Diff line change
Expand Up @@ -322,7 +322,7 @@ Vat) unless the `result` ID falls into one of these categories:
present in the C-List, and the Decider will point at this Vat.
* The Promise was received from the kernel earlier as the result slot of an
incoming message. The ID will be a negative integer, and the Decider will
point at this Vat.
point at this Vat. This is currently only allowed for a pipelining vat.

In all cases, the kernel promise table winds up with a Promise for which the
Decider is cleared, as the resolution authority now resides in the queued
Expand All @@ -340,6 +340,10 @@ to either create a new Promise (by passing the kernel a new positive
`PromiseID`, inside a `CapData` slot), or to receive it in the result slot of
an inbound message.

Once promise redirection is introduced, the effective decider of a promise
would change to the Decider of its redirection. However the Decider of record
may stay with the Kernel.

### Pipelining

Promise Pipelining is the practice of sending one message to the Decider of
Expand Down Expand Up @@ -373,6 +377,19 @@ pipelined deliveries, `dispatch.deliver()` is invoked and the message is sent
into the deciding Vat, which (in the case of the comms Vat) can transmit the
message to the remote machine where the target will be resolved.

There is currently a limitation that a message queued to the promise queue is
not moved back to the run-queue until resolution, even if the Decider changes
to a pipelining vat.

Once we implement per-vat or per-object queues, we may want to update the
Decider of a result promise as soon as the send is queued onto the vat. At that
point we would also queue pipeline eligible messages onto the target vat.
However such messages will need to be checked again before actual delivery in
case the target promise resolves, or the Decider changes before the message can
be delivered. This also implies that not all messages on a vat's queue are
doomed immediately when the vat is terminated, as there may have been
resolutions before termination that are still pending.

If a non-comms Vat enables pipelining, it is obligated to queue the pipelined
messages inside the Vat until the target is resolved. When that resolution
happens, the new target might be in some other Vat, in which case the
Expand Down Expand Up @@ -511,7 +528,7 @@ There are a few restrictions on the API:
* The `Message.result` in a `syscall.send()` must either be a new vat-allocated
(positive) PromiseID, or a previously-allocated PromiseID for which the
calling Vat is the Decider, or a PromiseID that was previously received as
the result of an inbound message.
the result of an inbound message (for pipelining vats).

Some invocation patterns are valid, but unlikely to be useful:

Expand All @@ -520,7 +537,7 @@ Some invocation patterns are valid, but unlikely to be useful:
which the local Vat is the Decider. In both cases, the Vat could have
delivered the message directly, instead of taking the time and effort of going
through the kernel's run-queue. On the other hand, this may achieve certain
ordering properties better.
ordering properties better, or allow the vat to split up work in multiple cranks.

In some places, `dispatch.deliver()` is named `message`: we're still in the
process of refactoring and unifying the codebase.
Expand Down Expand Up @@ -621,8 +638,9 @@ immediately after translation).
The subject of a `syscall.resolve()` must either be a new Promise ID, or a
pre-existing one for which the calling Vat is the Decider. The
`KernelPromise` must be in the `Unresolved` state. If any of these conditions
are not met, the Vat calling `resolve` will be terminated. It doesn't matter
whether the Promise was allocated by this Vat or a different one.
are not met, the Vat calling `resolve` will be terminated. Furthermore, only
pipelining-enabled vats are allowed to resolve promise IDs that they did not
allocate.

| Vat Object | action if missing |
| --- | --- |
Expand All @@ -632,7 +650,8 @@ whether the Promise was allocated by this Vat or a different one.
The `resolution` has several forms, and we assign a different name to each.

* `Fulfill(CapData)`: the Promise is "fulfilled" to a callable Object or other
data. It is an error to send messages to data.
data. It is an error to send messages to data. The CapData cannot be a single
promise as that would be a Forward.
* `Reject(CapData)`: the Promise is "rejected" to data which we call the
"error object". Sending a message to a Rejected Promise causes the result
of that message to be Rejected too, known as "rejection contagion".
Expand Down

0 comments on commit 1b7cead

Please sign in to comment.