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


5.3 Actormaps

So far we have dealt with vats, but there is a lower level of abstraction in Goblins which is called an actormap.

The key differences are:

The best way to learn is by doing, so let’s make an actormap now:

(define am (make-actormap))

Let’s add an actor to it. Since cells are simple, let’s add one of those.

(define lunchbox
  (actormap-spawn! am ^cell))

What’s in the lunchbox? We could take a look with actormap-peek:

> (actormap-peek am lunchbox)
; => #f

An empty lunchbox… we’d like to eat something later, so how about we pack ourselves a nice sandwich by using actormap-poke:

> (actormap-poke! am lunchbox 'peanut-butter-and-jelly)
> (actormap-peek am lunchbox)
; => 'peanut-butter-and-jelly

What if we tried to look inside the lunchbox with actormap-poke! instead of actormap-peek?

> (actormap-poke! am lunchbox 'bbq-tofu)
> (actormap-poke! am lunchbox)
; => 'bbq-tofu

Well that worked just fine. What happens if we do both operations with actormap-peek?

> (actormap-peek am lunchbox 'chickpea-salad)
> (actormap-peek am lunchbox)
; => 'bbq-tofu

What the…??? Our lunchbox didn’t change!

We said that actormaps were transactional. We have gotten a hint of this with the above: actormap-poke! returns a value and commits any changes. actormap-peek returns a value and throws any changes away.

Actually, these two functions are just simple conveniences that wrap a more powerful (but cumbersome to use) tool, actormap-turn:

> (actormap-turn am lunchbox)
; => 'bbq-tofu
; => #<transactormap>
; => '()
(actormap-turn am lunchbox 'chickpea-salad)
; => *unspecified* (not printed)
; => #<transactormap>
; => '()

actormap-turn returns three values to its continuation: a return value (if any… Guile’s REPL doesn’t print out the unspecified value, which is what actually got returned in the second invocation), a “transactormap”, and a list representing messages queued for delivery.

This #<transactormap> is interesting… we haven’t mentioned this before, but there are really two kinds of actormaps, “whactormaps” (weak-hash actormaps) and “transactormaps” (which hold a transaction which we can choose whether or not to commit). Actually our am is a whactormap:

> am
; => #<whactormap>

It’s a weak hashtable which stores the current mutable state of all actors.

But we’d like to see about that transactormap… just running actormap-turn on its own won’t update the lunchbox either:

> (actormap-turn am lunchbox 'chickpea-salad)
; => *unspecified* (not printed)
; => #<transactormap>
; => '()
> (actormap-turn am lunchbox)
; => 'bbq-tofu
; => #<transactormap>
; => '()

We need to capture the transactormap and commit it.

> (define-values (_val tr-am _nm)
    (actormap-turn am lunchbox 'chickpea-salad))
> tr-am
; => #<transactormap>
> (transactormap-merge! tr-am)

Now at least our am actormap should reflect that we’ve switched out our 'bbq-tofu sandwich for a 'chickpea-salad one:

> (actormap-peek am lunchbox)
; => 'chickpea-salad

Horray!


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