work on docs
This commit is contained in:
parent
a2780484be
commit
026e129de7
|
@ -3,20 +3,107 @@
|
|||
@(require (for-label (except-in racket process field)
|
||||
syndicate/actor))
|
||||
|
||||
@title{High Level Syntax for Syndicate}
|
||||
@title{Dataspace Programming with Syndicate}
|
||||
|
||||
|
||||
@defmodule[syndicate/actor]
|
||||
|
||||
@section{Instantaneous Actions (I)}
|
||||
@section{Overview}
|
||||
|
||||
@defform[(spawn I ...)]{
|
||||
Spawns an actor that executes each instantaneous action @racket[I] in
|
||||
sequence.}
|
||||
Syndicate is an actor language where all communication occurs through a tightly
|
||||
controlled shared memory, dubbed the @emph{dataspace}. The values in the
|
||||
dataspace are called @emph{assertions}, representing the information that the
|
||||
actors in the system are currently sharing with each other. Assertions are
|
||||
@emph{read-only} and @emph{owned} by the actor that entered them into the
|
||||
dataspace. Only the originating actor has permission to withdraw an assertion.
|
||||
Assertions are linked to the lifetime of their actor, and are withdrawn from the
|
||||
dataspace when that actor exits, either normally or via exception.
|
||||
|
||||
To respond to assertions in the dataspace, an actor expresses an @emph{interest}
|
||||
in the shape of assertions it wishes to receive. An interest is an assertion
|
||||
constructed with @racket[observe] and wildcards where the actor wishes to
|
||||
receive any matching assertion. When an actor makes an assertion of interest,
|
||||
the dataspace dispatches the set of all matching assertions to that actor.
|
||||
Moreover, the dataspace keeps the actor @emph{up-to-date}, informing it when a
|
||||
new assertion appears matching its interest, as well as when a matching
|
||||
assertion disappears from the dataspace. Thus, dataspaces implement a form of
|
||||
publish/subscribe communication.
|
||||
|
||||
@;{would be nice to link pub/sub}
|
||||
|
||||
In addition to assertions, dataspaces support instantaneous @racket[message]
|
||||
broadcast. At the time a message is sent, all actors with a matching interest
|
||||
receive notification.
|
||||
|
||||
In response to an event, that is, a message broadcast or assertion
|
||||
appearance/disappearance matching an expressed interest, a Syndicate actor may
|
||||
take any of the following actions:
|
||||
@itemlist[
|
||||
@item{Updating its internal state;}
|
||||
@item{Making or withdrawing assertions;}
|
||||
@item{Sending broadcast messages;}
|
||||
@item{Spawning additional actors;}
|
||||
@item{Exiting;}
|
||||
@item{Or any combination of these.}
|
||||
]
|
||||
|
||||
Thus, each individual Syndicate actor has three fudamental concerns:
|
||||
|
||||
@itemlist[
|
||||
@item{Defining local state and updating it in response to events;}
|
||||
@item{Publishing aspects of local state/knowledge as assertions; and}
|
||||
@item{Reacting to relevant assertions and messages.}
|
||||
]
|
||||
|
||||
Each concern is addressed by a separate language construct, which are
|
||||
collectively dubbed @emph{endpoints}:
|
||||
|
||||
@itemlist[
|
||||
@item{The @racket[field]s of an actor hold its state;}
|
||||
@item{An actor publishes information using @racket[assert]; and}
|
||||
@item{An event-handler endpoint uses @racket[on] to define reactions to
|
||||
particular messages and assertions.}
|
||||
]
|
||||
|
||||
Endpoints are tied together via @emph{dataflow}. Thus, the assertions of an
|
||||
actor automatically reflect the current value of its fields.
|
||||
|
||||
Implementing an actor's role in a particular conversation typically involves
|
||||
some combination of these behaviors; a @emph{facet} is a collection of related
|
||||
endpoints constituting the actor's participation in a particular conversation.
|
||||
|
||||
Each actor starts with a single facet, and may add new facets or terminate
|
||||
current ones in response to events. The facets of an actor form a tree, where
|
||||
the parent of a particular facet is the facet in which it was created. The tree
|
||||
structure affects facet shutdown; terminating a facet also terminates all of its
|
||||
descendants.
|
||||
|
||||
To recap: an actor is a tree of facets, each of which comprises of a collection
|
||||
of endpoints.
|
||||
|
||||
@section{Programming Syndicate Actors with Facets}
|
||||
|
||||
Code within Syndicate actors executes in one of two contexts:
|
||||
@itemlist[
|
||||
@item{The @emph{endpoint-installation} context occurs during the creation of a
|
||||
new facet, when all of its endpoints are created.}
|
||||
@item{The @emph{script} context occurs during the execution of event handlers,
|
||||
and permits creating/terminating facets, sending messages, and spawning
|
||||
actors.}
|
||||
]
|
||||
|
||||
The actions permitted by the two contexts are mutually exclusive, and trying to
|
||||
perform an action in the wrong context will give rise to a run-time
|
||||
@racket[error].
|
||||
|
||||
Within the following descriptions, we use @emph{EI} as a shorthand for
|
||||
expressions that execute in an endpoint-installation context and @emph{S} for
|
||||
expressions in a script context.
|
||||
|
||||
@defform[(spawn EI ...)]{
|
||||
Spawn an actor with a single inital facet whose endpoints are installed by
|
||||
@racket[EI]. That is, there is an implicit @racket[react] around @racket[EI ...].}
|
||||
|
||||
@defform[(dataspace I ...)]{
|
||||
Spawns a dataspace as a child of the dataspace enclosing the executing actor. The
|
||||
new dataspace executes each instantaneous action @racket[I].}
|
||||
|
||||
@defproc[(send! [v any/c]
|
||||
[#:meta-level level natural-number/c 0])
|
||||
|
@ -25,84 +112,6 @@ Sends a message with body @racket[v]. The message is sent @racket[level]
|
|||
dataspaces removed from the dataspace containing the actor performing the
|
||||
@racket[send!].}
|
||||
|
||||
@defproc[(assert! [v any/c]
|
||||
[#:meta-level level natural-number/c 0])
|
||||
void?]{
|
||||
Asserts the value of @racket[v] until either explicitly retracted via
|
||||
@racket[retract!] or the immediately enclosing actor exits. @racket[level]
|
||||
specifies which dataspace the assertion should be made, in terms of relative
|
||||
distance from the dataspace containing the enclosing actor.}
|
||||
|
||||
@defproc[(retract! [v any/c]
|
||||
[#:meta-level level natural-number/c 0])
|
||||
void?]{
|
||||
Retracts any assertions made by the immediately enclosing actor at
|
||||
@racket[level] dataspaces above the enclosing dataspace of the form @racket[v].}
|
||||
|
||||
@section{Ongoing Behaviors (O)}
|
||||
|
||||
@defform[(state maybe-init (maybe-bindings O ...) ([E I ...] ...))
|
||||
#:grammar
|
||||
[(maybe-init (code:line)
|
||||
(code:line #:init [I ...]))
|
||||
(maybe-bindings (code:line)
|
||||
(code:line #:collect ([id init] ...)))]
|
||||
#:contracts ([id identifier?])]{
|
||||
Spawns a new actor with ongoing behaviors @racket[O ...] that runs until a
|
||||
termination event is detected.
|
||||
|
||||
The optional @racket[#:init [I ...]] provides a sequence of initialization
|
||||
actions. The initial actions are executed before the ongoing behaviors begin but
|
||||
after the interests of the state actor are established.
|
||||
|
||||
The optional @racket[#:collect [(id init) ...]] clause introduces bindings that
|
||||
are visible within the body of the state actor. Each binding @racket[id] is
|
||||
initialized to the corresponding @racket[init] expression. The bindings are
|
||||
updated when an ongoing behavior executes an instantaneous event, such as the
|
||||
result of an @racket[on] behavior. The new bindings are in the form of a
|
||||
@racket[values] form, with the new values in the same order and number as in the
|
||||
@racket[#:collect].
|
||||
|
||||
The ongoing behaviors @racket[O ...] are run simultaneously until the state
|
||||
actor exits.
|
||||
|
||||
Each @racket[[E I ...]] specifies a termination event @racket[E] of the actor.
|
||||
When a termination event @racket[E] activates, the corresponding @racket[I]s are
|
||||
executed. The state actor then exits, with the same result of the final
|
||||
@racket[I] action.}
|
||||
|
||||
@defform[(until E
|
||||
maybe-init
|
||||
maybe-bindings
|
||||
maybe-done
|
||||
O ...)
|
||||
#:grammar
|
||||
[(maybe-init (code:line)
|
||||
(code:line #:init [I ...]))
|
||||
(maybe-bindings (code:line)
|
||||
(code:line #:collect ([id init] ...)))
|
||||
(maybe-done (code:line)
|
||||
(code:line #:done [I ...]))]
|
||||
#:contracts ([id identifier?])]{
|
||||
An @racket[until] behavior corresponds to a @racket[state] behavior with only
|
||||
one termination event, given by @racket[E]. The final result of the
|
||||
@racket[until] behavior is the values of the @racket[#:collect] bindings in
|
||||
scope from any parent actors followed by the final values of the @racket[until]
|
||||
actor's bindings. The actions in a @racket[#:done] clause are executed after the
|
||||
termination event but before the @racket[until] actor exits.}
|
||||
|
||||
@defform[(forever maybe-init
|
||||
maybe-bindings
|
||||
O ...)
|
||||
#:grammar
|
||||
[(maybe-init (code:line)
|
||||
(code:line #:init [I ...]))
|
||||
(maybe-bindings (code:line)
|
||||
(code:line #:collect ([id init] ...)))]
|
||||
#:contracts ([id identifier?])]{
|
||||
The @racket[forever] behavior is analogous to a @racket[state] form with no
|
||||
termination events.}
|
||||
|
||||
@defform[(during pat O ...)]{
|
||||
Runs the behaviors @racket[O ...] for the duration of each assertion matching
|
||||
@racket[pat].
|
||||
|
@ -178,3 +187,88 @@ to @racket[id].
|
|||
|
||||
@racket[expr] patterns match values that are exactly equal to @racket[expr].
|
||||
|
||||
@section{Actors with an Agenda}
|
||||
|
||||
Here we talk about @racket[spawn*] and @racket[react/suspend].
|
||||
|
||||
@section{Odds and Ends}
|
||||
|
||||
@defform[(dataspace I ...)]{
|
||||
Spawns a dataspace as a child of the dataspace enclosing the executing actor. The
|
||||
new dataspace executes each instantaneous action @racket[I].}
|
||||
|
||||
@defproc[(assert! [v any/c]
|
||||
[#:meta-level level natural-number/c 0])
|
||||
void?]{
|
||||
Asserts the value of @racket[v] until either explicitly retracted via
|
||||
@racket[retract!] or the immediately enclosing actor exits. @racket[level]
|
||||
specifies which dataspace the assertion should be made, in terms of relative
|
||||
distance from the dataspace containing the enclosing actor.}
|
||||
|
||||
@defproc[(retract! [v any/c]
|
||||
[#:meta-level level natural-number/c 0])
|
||||
void?]{
|
||||
Retracts any assertions made by the immediately enclosing actor at
|
||||
@racket[level] dataspaces above the enclosing dataspace of the form @racket[v].}
|
||||
|
||||
@defform[(state maybe-init (maybe-bindings O ...) ([E I ...] ...))
|
||||
#:grammar
|
||||
[(maybe-init (code:line)
|
||||
(code:line #:init [I ...]))
|
||||
(maybe-bindings (code:line)
|
||||
(code:line #:collect ([id init] ...)))]
|
||||
#:contracts ([id identifier?])]{
|
||||
Spawns a new actor with ongoing behaviors @racket[O ...] that runs until a
|
||||
termination event is detected.
|
||||
|
||||
The optional @racket[#:init [I ...]] provides a sequence of initialization
|
||||
actions. The initial actions are executed before the ongoing behaviors begin but
|
||||
after the interests of the state actor are established.
|
||||
|
||||
The optional @racket[#:collect [(id init) ...]] clause introduces bindings that
|
||||
are visible within the body of the state actor. Each binding @racket[id] is
|
||||
initialized to the corresponding @racket[init] expression. The bindings are
|
||||
updated when an ongoing behavior executes an instantaneous event, such as the
|
||||
result of an @racket[on] behavior. The new bindings are in the form of a
|
||||
@racket[values] form, with the new values in the same order and number as in the
|
||||
@racket[#:collect].
|
||||
|
||||
The ongoing behaviors @racket[O ...] are run simultaneously until the state
|
||||
actor exits.
|
||||
|
||||
Each @racket[[E I ...]] specifies a termination event @racket[E] of the actor.
|
||||
When a termination event @racket[E] activates, the corresponding @racket[I]s are
|
||||
executed. The state actor then exits, with the same result of the final
|
||||
@racket[I] action.}
|
||||
|
||||
@defform[(until E
|
||||
maybe-init
|
||||
maybe-bindings
|
||||
maybe-done
|
||||
O ...)
|
||||
#:grammar
|
||||
[(maybe-init (code:line)
|
||||
(code:line #:init [I ...]))
|
||||
(maybe-bindings (code:line)
|
||||
(code:line #:collect ([id init] ...)))
|
||||
(maybe-done (code:line)
|
||||
(code:line #:done [I ...]))]
|
||||
#:contracts ([id identifier?])]{
|
||||
An @racket[until] behavior corresponds to a @racket[state] behavior with only
|
||||
one termination event, given by @racket[E]. The final result of the
|
||||
@racket[until] behavior is the values of the @racket[#:collect] bindings in
|
||||
scope from any parent actors followed by the final values of the @racket[until]
|
||||
actor's bindings. The actions in a @racket[#:done] clause are executed after the
|
||||
termination event but before the @racket[until] actor exits.}
|
||||
|
||||
@defform[(forever maybe-init
|
||||
maybe-bindings
|
||||
O ...)
|
||||
#:grammar
|
||||
[(maybe-init (code:line)
|
||||
(code:line #:init [I ...]))
|
||||
(maybe-bindings (code:line)
|
||||
(code:line #:collect ([id init] ...)))]
|
||||
#:contracts ([id identifier?])]{
|
||||
The @racket[forever] behavior is analogous to a @racket[state] form with no
|
||||
termination events.}
|
||||
|
|
Loading…
Reference in New Issue