<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
selfrefers 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
wait-forever. All splats which contain looping constructs should call
check-completionon every iteration if possible.
finish circumvents the normal method-retrying routine.
Regardless of the
return-code, no further methods will be
finish is called on a splat.
(method-finish (self <splat>) return-code)
finish, except that if the
'method-succeededanother method is still selected by the normal method.
(check-completion (self <splat>))
check-completionis 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
check-completionwill not return. It invokes a continuation, saved before the selected method is run, to escape the method.
(start-task (child <splat>) (parent <splat>))
start-taskruns 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
(wait-for-task (child <splat>) (parent <splat>))
parentsplat until the
childfinishes. The value returned is the child's return code.
(run-top-level (child <splat>))
run-top-levelis shorthand for starting and waiting for a task with parent set to
#f. It blocks until the child finished.
(run (self <splat>))
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-actionsis 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
must be run with
start-task, or equivalent.
(parallel-actions a1 a2 ... an)
parallel-actionsis 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.
parallel-actions returns a
splat that must be run. Note that both
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-predcan be called within a method to block the splat until the predicate thunk
fluent-listis true. This is a wrapper around a
<splat-predicated-action>. See the
<splat-predicated-action>, section 5.3 for information on fluents and predicated actions.
(wait-forever (self <splat>))
wait-foreveris a wrapper around
wait-for-predwith 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>is a close relative of the
<splat>specialized for continuous closed-loop control laws rather than discrete actions.
(enable (behav <splat-behavior>))
enablecauses a thread to be created which runs the function defined in the
controlportion of the
define-behaviorform. This thread must periodically call
(disable (behav <splat-behavior>))
disablesets a flag which causes the behavior to exit the next time it calls
check-for-disable. After the thread leaves the
disablefunction (defined in the
define-behaviorform) is called.
(check-for-disable (self <splat-behavior>))
check-for-disablechecks for the flag set by a call to
disableand, if it is set, invokes a continuation saved before the thread was launched.
<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
event-handler portions of a
splat definition, and by the
splat-fluentobjects have two slots that are accessible at creation time via keywords.
Neither keyword argument is mandatory. If no
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
equiv-thunk returns false for a comparison of the old
value of the fluent and the new one specified by
splat-predicated-actionobjects have three mandatory keyword arguments to their constructor:
<splat-predicated-action>) which returns
#tif the consequent should be evaluated and
<splat-predicated-action>) which is run when the redicate becomes true.
<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
#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-fluentis the getter method, which fetches the value of the fluent under mutex protection.
(enable (action <splat-predicated-action>))
enableinstalls 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>))
disableis the opposite of
enable, removing the action from the notify list of the relevant fluents.