Control-flow actors
These actors provide control-flow constructs for other actors.
They send messages to user-specified
message groups as the results of
their actions -- looping, conditional statements, random number generation.
To use the LoopActor, load control.so and create an actor of type LoopActor.
LoopActor messages
The LoopActor periodically sends a single floating-point value to a message group.
You can control three aspects of the loop: initialization; termination conditions;
and step behavior (just like the three parts of a C-language for(;;) loop).
You can also control the number of times to repeat the loop, and optionally
"swing" back and forth through the loop.
A loop has three states: its data value, its elapsed time,
and how many steps (iterations) it has taken so far.
You can control the loop's execution with all three of these. Moreover, since
these produce an overdetermined system when taken as a whole, you can specify
which of these shall be constrained by the others (e.g., figure out what the
data and time increments will be, given a data range of 0 to 10,
a time duration of 20 seconds, and exactly 42 steps through the loop).
This is trickier than it looks. Watch out particularly that you terminate
the loop in the way you intend to: when the data value reaches a limit,
when a fixed number of steps have completed, or when a certain amount of
time has elapsed. (If you don't do one of these things, the loop is infinite.)
The default loop "does nothing": it sends out a stream of zeros, unchanging,
without termination. (It only does this once a message group has been set to
receive the stream, and once a SetNumLoops message has activated it, though.)
In addition to the messages understood by all actors,
the LoopActor understands the following messages:
- Loop Initialization
- SetDataStart hActor x
- Set the starting data value of the loop to x.
- Loop Stepping
- SetDataStep hActor xDelta [time]
- Each time through the loop, increment the data value by xDelta
(default 0).
If time is specified, linearly change the value of xDelta
from its current value to the new value over the next time seconds.
- SetTimeStep hActor tDelta [time]
- Each time through the loop, pause for tDelta seconds (default 1).
tDelta must be nonnegative.
If time is specified, linearly change the value of tDelta
from its current value to the new value over the next time seconds.
- Loop Termination -
The loop will terminate if any one of these conditions holds (logical "or").
- SetDataLimit hActor xLimit
- Terminate loop when the data value x passes xLimit,
considering the sign of SetDataStep. (If the argument of the last
SetDataStep was positive,
terminate when x exceeds xLimit;
if negative, when x falls below xLimit.)
- SetNoDataLimit hActor
- Ignore any previous SetDataLimit messages
when checking for loop termination. This is the default.
- SetTimeLimit hActor tLimit
- Terminate loop when tLimit seconds have elapsed since the loop
started running (by sending a SetNumLoops message).
If tLimit is negative (the default), ignore time limits.
- SetStepLimit hActor stepLimit
- Terminate loop after the stepLimit'th step through the loop.
If stepLimit is negative (the default), ignore step limits.
- Constraint Definition -
Of course, these may be inaccurate if values change during the loop's execution,
e.g. as a result of gradual acceleration in SetTimeStep above.
- ComputeDataLimit hActor
- ComputeDataStep hActor
- Compute this value so the data reaches its limit at the same time
as the first of (time, steps) reaches its limit.
- ComputeTimeLimit hActor
- ComputeTimeStep hActor
- Compute this value so the time reaches its limit at the same time
as the first of (data, steps) reaches its limit.
- ComputeStepLimit hActor
- Compute this value so the step reaches its limit at the same time
as the first of (data, time) reaches its limit.
- Miscellany
- SetMessageGroup hActor messageGroupName
- Assign a message group to send the periodic messages to. These
messages will have two arguments ("*0, *1"), the current data
value of the loop and the most recent value sent to SetUserFloat respectively.
- SetNumLoops hActor numLoops
- Run the loop for numLoops times. You'll commonly use a value of 1.
(If the loop is currently running,
it will restart from the beginning and do its thing numLoops times
starting from now, irrespective of any previous SetNumLoops commands.)
If numLoops is zero (the default),
the loop will immediately halt and remain halted until a nonzero
SetNumLoops message is received.
If numLoops is negative, the loop will run indefinitely.
- SetSwing hActor bool
- Enable or disable Swing Mode.
If bool is true (nonzero), each time the loop terminates,
the start and limit data values are exchanged and the data step is negated,
so the next execution of the loop is "reversed" with respect to the data.
If SetNumLoops has a large value, this causes the data value to "swing"
back and forth between its two extremes.
The default value is false.
- Debug hActor bool
- Enable or disable Debug Mode.
If bool is true (nonzero), the full state of the loop (start,
end, step, and current values of data, time, and step; and swing and
numloops values) is printed just after each step of the loop
and just after each message received by the LoopActor.
- SetUserFloat hActor x
- Assign a new value to this variable, simply to pass it along
to the message group named in SetMessageGroup as a second
parameter.
Examples
LoadDSO debug.so;
pr = Create PrintfActor;
// This prints debugging messages.
LoadDSO msgGroup.so;
printme = Create MessageGroup;
AddMessage printme printf pr *0;
// Call this message group to print a number.
LoadDSO control.so;
loop = Create LoopActor;
SetMessageGroup loop printme;
// Attach mg to our loop actor, so our loop will print numbers.
- Print 2, 4, 6, 8, one number per second (with debugging info):
Active loop 0;
Debug loop 1;
SetNumLoops loop 1;
SetDataStart loop 2;
SetDataStep loop 2;
SetDataLimit loop 8;
Active loop 1;
sleep 15;
- Print 2, 4, 6, 8, one number per second, for one hour:
Active loop 0;
SetNumLoops loop -1; // loop forever
SetDataStart loop 2;
SetDataStep loop 2;
SetDataLimit loop 8;
Active loop 1;
sleep 3600;
- Print 2, 4, 6, 8, 6, 4, 2, ten numbers per second, for one minute:
Active loop 0;
SetSwing loop 1; // back and forth
SetTimeStep loop 0.1;
SetNumLoops loop -1; // loop forever
SetDataStart loop 2;
SetDataStep loop 2;
SetDataLimit loop 8;
Active loop 1;
sleep 60;
- Print increasing even numbers, ten per second, for one minute:
Active loop 0;
SetSwing loop 1;
SetTimeStep loop 0.1;
SetTimeLimit loop 60; // this replaces SetDataLimit as termination condition
SetNumLoops loop 1; // do this only once
SetDataStart loop 2;
SetDataStep loop 2;
Active loop 1;
sleep 65;
- Print "42" ten times:
Active loop 0;
SetStepLimit loop 9; // "for (i=0; i<=9; i++)"
SetDataStart loop 42;
SetDataStep loop 0; // Don't change 42 to anything else (default)
SetNumLoops loop 1;
Active loop 1;
sleep 60;
- Print "42" ten times (using 10 loops, instead of 10 steps through one loop):
Active loop 0;
SetStepLimit loop 0; // "for (i=0; i<=0; i++)"
SetDataStart loop 42;
SetNumLoops loop 10; // Do all of the above ten times
Active loop 1;
sleep 60;
- Print "42" ten times (using 2 loops of 5 steps each):
Active loop 0;
SetStepLimit loop 4; // "for (i=0; i<=4; i++)"
SetDataStart loop 42;
SetNumLoops loop 2; // Do it twice
Active loop 1;
sleep 60;