|
|
|
|
@ -32,12 +32,12 @@
|
|
|
|
|
|
|
|
|
|
Goblins implements the |
|
|
|
|
@link["https://en.wikipedia.org/wiki/Actor_model"]{actor model} |
|
|
|
|
on top of Racket / scheme.@actors-note{ |
|
|
|
|
on top of Racket / Scheme.@actors-note{ |
|
|
|
|
Sussman and Steele famously came to the conclusion that there was in |
|
|
|
|
fact no difference between actor-style message passing and procedure |
|
|
|
|
application in the lambda calculus, and indeed both are similar. |
|
|
|
|
However, there is a significant difference between synchronous |
|
|
|
|
call-and-return procedure application (which is what scheme implements |
|
|
|
|
call-and-return procedure application (which is what Scheme implements |
|
|
|
|
in its most general form, and between actors in Goblins is handled |
|
|
|
|
by @racket[$]) and asynchronous message passing (which in Goblins |
|
|
|
|
is handled with @racket[<-]).} |
|
|
|
|
@ -67,7 +67,7 @@ Goblins' extensions to these ideas are:
|
|
|
|
|
@item{@emph{Both} synchronous and asynchronous calls are defined and |
|
|
|
|
supported, between @racket[$] and @racket[<-] respectively. |
|
|
|
|
However, @racket[$] is both convenient and important for systems |
|
|
|
|
that much be transactionally atomic (eg |
|
|
|
|
that must be transactionally atomic (e.g. |
|
|
|
|
@link["http://erights.org/elib/capability/ode/ode-capabilities.html"]{implementing money}), |
|
|
|
|
it is limited to objects that are within the same @tech{vat}. |
|
|
|
|
@racket[<-] is more universal in that any actor on any @tech{vat} |
|
|
|
|
@ -79,12 +79,12 @@ Goblins' extensions to these ideas are:
|
|
|
|
|
to move from a coroutine-centric approach to an |
|
|
|
|
@link["http://www.erights.org/"]{E}-style promise approach. |
|
|
|
|
It could be that coroutines are re-added, but would have to be done |
|
|
|
|
with extreme care; section 18.2 of that same thesis for an |
|
|
|
|
explaination of the challenges and a possible solution for |
|
|
|
|
with extreme care. Section 18.2 of that same thesis for an |
|
|
|
|
explanation of the challenges and a possible solution for |
|
|
|
|
introducing coroutines.}} |
|
|
|
|
@item{Raw message passing without a clear way to get values back can |
|
|
|
|
be painful. |
|
|
|
|
For this reason, @racket[<-] implicitly returns a promise that |
|
|
|
|
For this reason, @racket[<-], implicitly returns a promise that |
|
|
|
|
can be resolved with @racket[on] (and, for extra convenience and |
|
|
|
|
fewer round trips, supports |
|
|
|
|
@secref["promise pipelining (tutorial)"]).@actors-note{ |
|
|
|
|
@ -93,7 +93,7 @@ Goblins' extensions to these ideas are:
|
|
|
|
|
The kind of value that promises give us can be constructed manually |
|
|
|
|
by providing return addresses to @racket[<-np], but this is painful |
|
|
|
|
given how common needing to operate on the result of an operation is.}} |
|
|
|
|
@item{Goblins composes with all the existing machinery of Racket/scheme, |
|
|
|
|
@item{Goblins composes with all the existing machinery of Racket/Scheme, |
|
|
|
|
including normal procedure calls. |
|
|
|
|
Instead, Goblins builds its abstractions on top of it, but none of this |
|
|
|
|
needs to be thrown away.@actors-note{ |
|
|
|
|
@ -109,7 +109,7 @@ Goblins' extensions to these ideas are:
|
|
|
|
|
A @deftech{constructor} is a procedure which builds the first message |
|
|
|
|
handler an actor will use to process messages / invocations. |
|
|
|
|
The constructor has one mandatory argument, traditionally called |
|
|
|
|
@tech{bcom} (pronounced "become" or "bee-com") which can be used |
|
|
|
|
@tech{bcom} (pronounced "become" or "bee-com"), which can be used |
|
|
|
|
to set up a new message handler for future invocations. |
|
|
|
|
|
|
|
|
|
@interact[ |
|
|
|
|
@ -189,7 +189,7 @@ argument passed to its @racket[bcom], or void if not provided.)
|
|
|
|
|
Exceptions raised by @racket[actor-refr]'s invocation will be |
|
|
|
|
propagated and can be captured. |
|
|
|
|
|
|
|
|
|
Note that excape continuations can be set up between a caller of |
|
|
|
|
@bold{NOTE:} that escape continuations can be set up between a caller of |
|
|
|
|
@racket[$] and can be used by the callee. However, a |
|
|
|
|
@tech[#:doc '(lib "scribblings/reference/reference.scrbl")]{continuation barrier} |
|
|
|
|
is installed and so capturing of the continuation is not possible. |
|
|
|
|
@ -342,7 +342,7 @@ Actormaps are also wrapped by @tech{vat}s.
|
|
|
|
|
More commonly, users will use vats than actormaps directly; however, |
|
|
|
|
there are some powerful aspects to doing so, namely for |
|
|
|
|
strictly-synchronous programs (such as games) or for snapshotting |
|
|
|
|
actormaps for time-traveling purposese. |
|
|
|
|
actormaps for time-traveling purposes. |
|
|
|
|
|
|
|
|
|
In general, there are really two key operations for operating on |
|
|
|
|
actormaps. |
|
|
|
|
@ -351,9 +351,9 @@ bootstrap an actormap with some interesting actors.
|
|
|
|
|
Actors then operate on @deftech[#:key "turn"]{turns}, which are |
|
|
|
|
basically a top-level invocation; the core operation for that is |
|
|
|
|
@racket[actormap-turn]. |
|
|
|
|
This can be thought of as like a toplevel invocation of a procedure at |
|
|
|
|
This can be thought of as like a top-level invocation of a procedure at |
|
|
|
|
a REPL: the procedure called may create other objects, instantiate and |
|
|
|
|
call other procedures, etc, but (unless some portion of computation |
|
|
|
|
call other procedures, etc., but (unless some portion of computation |
|
|
|
|
goes into an infinite loop) will eventually return to the REPL with |
|
|
|
|
some value. |
|
|
|
|
Actormap turns are similar; actors may do |
|
|
|
|
@ -392,7 +392,7 @@ Returns two values to its continuation, the new actor @tech{live}
|
|
|
|
|
[actor-refr live-refr?]]{ |
|
|
|
|
Like @racket[actormap-spawn], but directly commits the actor to |
|
|
|
|
@racket[actormap]. |
|
|
|
|
Only returns the tech{reference} of the new actor. |
|
|
|
|
Only returns the @tech{reference} of the new actor. |
|
|
|
|
No changes are committed in an exceptional condition.} |
|
|
|
|
|
|
|
|
|
@defproc[(actormap-turn [actormap actormap?] [to-refr live-refr?] [args any/c] ...) |
|
|
|
|
@ -422,7 +422,7 @@ back".
|
|
|
|
|
any/c]{ |
|
|
|
|
Similar to performing @racket[$], applying @racket[args] to |
|
|
|
|
@racket[to-refr]. |
|
|
|
|
Commits its result immediately, barring an exceptional condition.} |
|
|
|
|
Commit its result immediately, barring an exceptional condition.} |
|
|
|
|
|
|
|
|
|
@defproc[(actormap-peek [actormap actormap?] [to-refr live-refr?] [args any/c] ...) |
|
|
|
|
void?]{ |
|
|
|
|
@ -432,7 +432,7 @@ become-effects within it.}
|
|
|
|
|
|
|
|
|
|
@defproc[(actormap-run [actormap actormap?] [proc (-> any/c)]) any/c]{ |
|
|
|
|
Run @racket[proc], which is a thunk (procedure with no arguments) in the |
|
|
|
|
actormap context, but do not commit its results, instead returning its |
|
|
|
|
actormap context, but does not commit its result, instead returning its |
|
|
|
|
value. |
|
|
|
|
|
|
|
|
|
Like @racket[actormap-peek], this is useful for interrogating an |
|
|
|
|
@ -442,7 +442,7 @@ actormap, but can be useful for doing several things at once.}
|
|
|
|
|
[proc (-> any)] |
|
|
|
|
[#:reckless? reckless? any/c #f]) |
|
|
|
|
any]{ |
|
|
|
|
Like @racket[actormap-run], but commits results like @racket[actormap-poke!] when |
|
|
|
|
Like @racket[actormap-run], but commits a result like @racket[actormap-poke!] when |
|
|
|
|
@racket[reckless?] is #f, else it commits results like @racket[actormap-reckless-poke!]. |
|
|
|
|
Unlike @racket[actormap-run], it can return multiple values.} |
|
|
|
|
|
|
|
|
|
@ -487,7 +487,7 @@ It is unlikely you will need this procedure, since @racket[actormap-turn],
|
|
|
|
|
Recursively merges this and any parent @tech{transactormap}s until it reaches |
|
|
|
|
the root @tech{whactormap}. |
|
|
|
|
|
|
|
|
|
Note that creating two forking timelines of transactormaps upon a |
|
|
|
|
@bold{NOTE:} that creating two forking timelines of transactormaps upon a |
|
|
|
|
whactormap and merging them may corrupt your whactormap.} |
|
|
|
|
|
|
|
|
|
@defproc[(transactormap-merged? [transactormap transactormap?]) boolean?]{ |
|
|
|
|
@ -576,7 +576,7 @@ Since then, a number of readers of this documentation have complained
|
|
|
|
|
that "vat" is confusing, and upon hearing this story have asked for |
|
|
|
|
the term to be switched back. |
|
|
|
|
Whether it's better to avoid naming fragmentation or possibly increase |
|
|
|
|
naming clarity is currently up for debate; your feedback welcome!} |
|
|
|
|
naming clarity is currently up for debate; your feedback is welcome!} |
|
|
|
|
is an event loop that wraps an @tech{actormap}. |
|
|
|
|
In most cases, users will use vats rather than the more low-level |
|
|
|
|
actormaps. |
|
|
|
|
|