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


4.5 Asynchronous message passing

We have shown that the behavior of objects may be invoked synchronously with $. However, this only works if two objects are both defined on the same machine on the network and the same event loop within that machine.

Now, recall our friend alice who we defined on vat A. The following works just fine if we’re still executing within a-vat’s subrepl context:

goblins[1]> ($ alice "Alfred")
=> "Hello Alfred, my name is Alice!"

But let’s exit the a-vat subrepl and make b-vat and enter that:

goblins[1]> ,q
scheme> (define b-vat
          (spawn-vat))
scheme> ,enter-vat b-vat
goblins[1]>

But since Alice works on A, we cannot synchronously invoke her with $ on vat B:

goblins[1]> ($ alice "Bob")
;; === Caught error: ===
;;  message: #<<message> to: #<local-object> resolve-me: #f args: ()>
;;  exception: ... "Not in the same vat:" #<local-object ^greeter>) ...

This is where <- comes in. In contrast to $, <- can be used against objects which live anywhere, even on remote machines. However, unlike invocation with $, we do not get back an immediate result, we get a promise:

goblins[1]> (<- alice "Bob")
; => #<promise>

This promise must be listened to. The procedure to listen to promises in Goblins is called on:

goblins[1]> (on (<- alice "Bob")
                (lambda (got-back)
                  (format #t "Heard back: ~a\n"
                          got-back)))
; Prints out, at some point in the future:
;   "Heard back: [3] Hello Bob, my name is Alice!"

Not all communication goes as planned, especially in a distributed system. Consider an object which breaks in the middle of execution, such as an instance of ^broken here:

(define (^broken _bcom)
  (lambda ()
    (error "Yikes, I broke!")))

on also supports the keyword arguments of #:catch and #:finally, which both accept a procedure defining handling errors in the former case and code which will run regardless of successful resolution or failure in the latter case:

goblins[1]> (define broken-ben
              (spawn ^broken-ben))
goblins[1]> (on (<- broken-ben)
                (lambda (what-did-ben-say)
                  (format #t "Ben says: ~a\n" what-did-ben-say))
                #:catch
                (lambda (err)
                  (format #t "Got an error: ~a\n" err))
                #:finally
                (lambda ()
                  (display "Whew, it's over!\n")))

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