Previous: , Up: Tutorial   [Contents][Index]

4.7 Promise pipelining

“Machines grow faster and memories grow larger. But the speed of light is constant and New York is not getting any closer to Tokyo.”

— Mark S. Miller, Robust Composition: Towards a Unified Approach to Access Control and Concurrency Control

Promise pipelining provides two different features at once:

Consider the following car factory, which makes cars carrying the company name of the factory:

;; Create a "car factory", which makes cars branded with
;; company-name.
(define (^car-factory bcom company-name)
  ;; The constructor for cars we will create.
  (define (^car bcom model color)
    (methods                      ; methods for the ^car
     ((drive)                    ; drive the car
      (format #f "*Vroom vroom!*  You drive your ~a ~a ~a!"
              color company-name model))))
  ;; methods for the ^car-factory instance
  (methods                        ; methods for the ^car-factory
   ((make-car model color)       ; create a car
    (spawn ^car model color))))

Here is an instance of this car factory, called fork-motors and spawned in a-vat:

scheme> ,enter-vat a-vat
goblins[1]> (define fork-motors
              (spawn ^car-factory "Fork"))

Since asynchronous message passing with <- works across nodes, it does not matter whether interactions with fork-motors are local or via objects communicating over the network. This example treat fork-motors as living on node A, and so the following interactions will happen with invocations originating from node B.

Now send a message to fork-motors invoking the 'make-car method, receiving back a promise for the car which will be made, which will be name car-vow (-vow being the conventional suffix given for promises in Goblins):

goblins[1]> ,q
scheme> ,enter-vat b-vat
;; Interaction on node B, communicating with fork-motors on A
goblins[1]> (define car-vow
              (<- fork-motors 'make-car "Explorist" "blue"))

So you have a promise to a future car reference, but not the reference itself. You would like to drive the car as soon as it rolls off the lot of the factory, which of course involves sending a message to the car.

Without promise pipelining, making use of the tools already shown (and following the pattern most other distributed programming systems use), you would end up with something like:

;; Interaction on node B, communicating with A
goblins[1]> (on car-vow                    ; B->A: first resolve the car-vow
                (lambda (our-car)          ; A->B: car-vow resolved as our-car
                  (on (<- our-car 'drive)  ; B->A: now we can message our-car
                      (lambda (val)        ; A->B: result of that message
                        (format #f "Heard: ~a\n" val)))))

With promise pipelining, you can simply message the promise of the car directly. The first benefit can be observed from code compactness, in that you do not need to do an on of car-vow to later message our-car; you can simply message car-vow directly:

;; Interaction on node B, communicating with A
goblins[1]> (on (<- car-vow 'drive)       ; B->A: send message to future car
                (lambda (val)             ; A->B: result of that message
                  (format #t "Heard: ~a\n" val)))

While clearly a considerable programming convenience, the other advantage of promise pipelining is a reduction of round-trips, whether between event-loop vats or across nodes on the network.

This can be understood by looking at the comments to the right of the two above code interactions. The message flow in the first case looks like:

B => A => B => A => B

The message flow in the second case looks like:

B => A => B

In other words, node B can say to node A: “Make me a car, and as soon as that car is ready, I want to drive it!”

With this in mind, the promise behind Mark Miller’s quote at the beginning of this section is clear.1 If two objects are on opposite ends of the planet, round trips are unavoidably expensive. Promise pipelining both allows programmers to make plans and allows Goblins to optimize carrying out those steps as bulk operations over the network.



Like so many examples in this document, the designs of promise pipelining and the explanation of its value come from the E programming language, the many contributors to its design, and Mark S. Miller’s extraordinary work documenting that work and its history. If you find this section interesting, see both the Promise Pipelining page from and sections 2.5 and 16.2 of Mark Miller’s dissertation.

Previous: Transactions make errors survivable, Up: Tutorial   [Contents][Index]