<splat>
<splat>
data type is a structure that contains
information about an instantiated splat, returned from the
instantiation function. Most of the methods of this class are only
used by the thread controlling splt execution, or by the various
special syntax forms. However, some methods are directly useful to
the splat writer.
(finish (self <splat>) return-code)
return-code
.
If the splat self
refers to the splat in which the call takes
place (i.e. the splat is finishing itself) termination takes place
immediately. If the splat to finish is other than the current splat,
the target does not terminate until its next call to
check-completion
, wait-for-pred
,
wait-for-task
, or wait-forever
. All splats which
contain looping constructs should call check-completion
on
every iteration if possible.
finish
circumvents the normal method-retrying routine.
Regardless of the return-code
, no further methods will be
selected after finish
is called on a splat.
(method-finish (self <splat>) return-code)
method-finish
behaves like finish
, except that if
the return-code
is not 'method-succeeded
another
method is still selected by the normal method.
(check-completion (self <splat>))
check-completion
is the synchronization point for splat
cancellation. It must be called periodically to allow parents or
other splats to terminate a task. If another splat has called
finish
or method-finish
on self
,
check-completion
will not return. It invokes a continuation,
saved before the selected method is run, to escape the method.
(start-task (child <splat>) (parent <splat>))
start-task
runs a child splat (as returned from an
instantiation function) under the control of the specified parent. To
run a splat from the top-level read-eval-print loop, use #f
for parent
.
(wait-for-task (child <splat>) (parent <splat>))
wait-for-task
blocks the parent
splat until the
child
finishes. The value returned is the child's return
code.
(run-top-level (child <splat>))
run-top-level
is shorthand for starting and waiting for a
task with parent set to #f
. It blocks until the child
finished.
(run (self <splat>))
run
is like run-top-level
, except that it can only
be used within the body of a splat to run a child of the current splat.
(sequence-actions a1 a2 ... an)
sequence-actions
is a special form which builds a temporary
splat with one method which launches and waits for the splats a1
... an in sequential order. If any of the splats fail, the
sequence is short-circuited.
Like any other splat, the one returned from sequence-actions
must be run with run
, start-task
, or equivalent.
(parallel-actions a1 a2 ... an)
parallel-actions
is a special form which builds a temporary
splat with one method which launches all splats a1 ... an and
then waits for all of them to finish. If any of the splats fails,
the sequence is aborted.
Like sequence-actions
, parallel-actions
returns a
splat that must be run. Note that both sequence-actions
and parallel-actions
launch and wait for all their children, so
when calls to these forms are nested (which is perfectly acceptable)
only the top-most form needs to be explicitly run. In this example,
the floor mopping and table cleaning can be done in parallel, but the
table can't be wiped until the glass is picked up:
(define-splat (clean-up-spilled-milk (mop <cleaning-tool>) (rag <cleaning-tool>)) (method #t (run (parallel-actions (dont-cry) (sequence-actions (wipe-feet rag) (mop-floor mop)) (sequence-actions (pick-up-glass) (wipe-table rag)))))
This idiom allows the construction of arbitrarily-sequenced parallel and sequential actions.
(wait-for-pred (self <splat>) fluent-list pred)
wait-for-pred
can be called within a method to block the
splat until the predicate thunk pred
on fluents
fluent-list
is true. This is a wrapper around a
<splat-predicated-action>
. See the
<splat-fluent>
documentation in
<splat-fluent>
and <splat-predicated-action>
, section 5.3 for information on fluents and
predicated actions.
(wait-forever (self <splat>))
wait-forever
is a wrapper around wait-for-pred
with
a predicate of (lambda () #f)
. This function can be used
when waiting for an event handler to be triggered by an external
event.
<splat-behavior>
<splat-behavior>
is a close relative of the
<splat>
specialized for continuous closed-loop control
laws rather than discrete actions.
(enable (behav <splat-behavior>))
enable
causes a thread to be created which runs the function
defined in the control
portion of the
define-behavior
form. This thread must periodically call
check-for-disable
.
(disable (behav <splat-behavior>))
disable
sets a flag which causes the behavior to exit the
next time it calls check-for-disable
. After the thread
leaves the control
function, the disable
function
(defined in the define-behavior
form) is called.
(check-for-disable (self <splat-behavior>))
check-for-disable
checks for the flag set by a call to
disable
and, if it is set, invokes a continuation saved
before the thread was launched.
<splat-fluent>
and <splat-predicated-action>
<splat-fluent>
class, together with the
<splat-predicated-action>
class, provides a basic
synchronization mechanism for splats. A predicated action is a form
of "callback" which has a predicate and a consequent. When the
predicate becomes true, the consequent is evaluated.
The only way to avoid polling is somehow to be aware of any operation that could cause the predicate to become true and test the predicate when they change. We handle this by tagging each predicate thunk with a list of all the variables that can be changed externally to alter its truth value, and then wrapping access to those variables in functions that keep pointers to all the predicated actions that depend on those variables.
The wrapped variable is of type <splat-fluent>
, and a
combination of predicate, consequent, and a list of fluents is a
<splat-predicated-action>
. Predicated actions are used
for the wait-for
and event-handler
portions of a
splat definition, and by the wait-for-pred
function.
(make <splat-fluent>)
splat-fluent
objects have two slots that are accessible at
creation time via keywords.
binding:
equiv-thunk:
Neither keyword argument is mandatory. If no equiv-thunk
is
specified, predicates for actions that depend on the fluent are
evaluated every time the set-fluent!
method is called. If an
equiv-thunk
is specified, the predicates are only tested if
the equiv-thunk
returns false for a comparison of the old
value of the fluent and the new one specified by set-fluent!
.
(make <splat-predicated-action>)
splat-predicated-action
objects have three mandatory
keyword arguments to their constructor:
predicate:
<splat-predicated-action>
) which returns #t
if the consequent should be evaluated and #f
otherwise.action:
<splat-predicated-action>
) which is run when the
redicate becomes true.fluents:
<splat-fluent>
which
should cause the predicate to be evaluated when changed.
The default behavior is one-shot. The action is only invoked
once, and future #f
--#t
transitions of the predicate
will not cause the action to be invoked. If repeated behavior is
desired, call the enable
method from within the action thunk.
(set-fluent! (fluent <splat-fluent>) value)
set-fluent!
binds the fluent's value slot to value
.
This method is responsible for evaluating any predicates of predicated
actions which depend on the fluent, and running the consequent of any
predicates which become true. As such, there can be a
not-insignificant time cost for invoking set-fluent!
. Any
number of predicate and consequent thunks for various predicated
actions could conceivably be executed before the setter returns.
(get-fluent (fluent <splat-fluent>) value)
get-fluent
is the getter method, which fetches the value of
the fluent under mutex protection.
(enable (action <splat-predicated-action>))
enable
installs handlers that allow fluents to check the
predicate when they change. A predicated action must be enabled to
have a chance to run its action. They are not enabled on creation,
and must be re-enabled in the action-thunk if one-shot behavior is not
desired.
(disable (action <splat-predicated-action>))
disable
is the opposite of enable
, removing the
action from the notify list of the relevant fluents.