Next: OCapN The Object Capabilities Network, Previous: Vats, Up: API [Contents]
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: OCapN The Object Capabilities Network, Previous: Vats, Up: API [Contents]