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


4.5 Asynchronous message passing

You have seen that the behavior of objects may be invoked synchronously with $. However, this only works if two objects are both defined on the same node and the same event loop (vat) within that node.

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

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

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]>

Since Alice works on A, you 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 nodes on remote machines across a network. However, unlike invocation with $, you do not get back an immediate result; you 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))
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: Transactions make errors survivable, Previous: Objects which contain objects, Up: Tutorial   [Contents][Index]