NAME
while_idle -- periodically invoke operands during idle time
PROTOTYPE
unitptr while_idle( int iOperands, float fDelta, int iPriority, char *pcOptions, unitptr uHost)
ARGUMENTS
- int iOperands
- nr of operands
- float fDelta
- target time interval between invocations (in msec)
- int iPriority
- priority group: 0 = allow execution only when Neo main loop is idle 1 = allow execution also when NST GUIs are waiting
- char *pcOptions
- options [currently unused]
- unitptr uHost
- host unit
RETURN VALUE:
A pointer to the created unit or NULL in the case of an error.
INTERFACE OF CREATED UNIT:
- CTL_in[]:
- (control field) A value of 0 disables the unit.
SYNOPSIS:
This is a special operator unit that periodically executes its
operands whenever there is idle time, i.e., when the main event loop
waits for input. Using several instances of this unit therefore allows
to "fake" concurrency (with a minimal temporal resolution of
about 10msec on a 200 Mhz Pentium).
DESCRIPTION:
This is a special operator unit that cannot be executed by the user.
Instead, it periodically executes its operands whenever there is
idle time (i.e., when the main event loop waits for input) and
a prespecified time interval (parameter fDelta) has elapsed since
its last invocation.
Each while_idle instance has a next schedule time for invocation
(the schedule times of a particular instance try to be about
fDelta msecs apart). Whenever there is idle time, NST will choose
the while_idle instance with the nearest schedule time and execute
it (which means executing each of its operands once). Then, the
executed unit's schedule time will be incremented by the fDelta time
parameter that was defined for that unit. This gives another unit
the chance to become picked on the next occasion.
The time spacing between invocations of an instance may be too short
to be actually met. In this case, NST tries to come close. Further
modifications to the scheduling policy (raising the priority of
unexecuted while_idle instances) ensure that the unit with
the shortest schedule interval will not "shadow" all the others
when the system load is too high to keep up with the schedule.
When all involved units execute rapidly, there is practically
always idle time and the effect is a "simulated" concurrency,
without the intricacies of threads. Only when NST becomes involved
into a longer chain of uninterrupted operations (i.e., a for_op
with many iterations), the operation of the while_idle units
becomes blocked.
Conversely, if the operands of while_idle unit require
significant execution time, they may hamper the smooth operation
of the Neo and NST GUIs. If this is a problem, one may forbid the
concurrent execution of while_idle units at least during times
when a NST GUI is active.
NOTES:
The exec, ctrl and adapt methods of the while_idle unit itself
do nothing. The unit only serves to define a group of operand
units and a timing interval for the automatic calls from the
NST/Neo event loops.
The return_unit among the operand units allows a premature
return from an invocation.
Nesting of while_idle units is without effect: when a while_idle
instance is the operand of another one, the inner while_idle instance
will no longer auto-invoke itself and will do nothing when invoked
from outside.
When the execution time of the operands of a while_idle exceeds
the scheduled time by more than 2 seconds, a warning is issued
and the while_idle unit is excluded from further auto-invocations
to avoid unwanted blocking of the remaining circuit. This is done
by zeroing its control pin. To re-activate the unit, restore the
nonzero ctl pin value (e.g., remake the unit).
Execution of a circuit with while_idle units without Neo
from within a C/C++ program (using the nstloa library) may
leave the while_idle units uninvoked, since there is no
Neo main loop present (invocations from within NST GUIs still
would continue to work, however). As a remedy, the program
may use explicit calls of nst_servic_idle_tasks(iPrioGroup)
with iPrioGroup=0 or 1, or, even better, when it has a
main event loop, embed a nst_service_idle_tasks() call
therein.
DETAILS OF SCHEDULING POLICY:
NST and/or Neo tries to execute while_idle instances on two
occasions:
1. when the Neo main loop is idle, all while_idle instances
with nonzero control pin are considered
2. when NST waits through one of the routines nst_wait_for_event(),
nst_wait_for_widget_event() or nst_wait_for_window_or_subwindow_event(),
all while_idle instances with nonzero control pin in priority groups 1
or higher are considered. [the above routines are used in the
NST GUI and mouse units]
When all schedule times of all considered while_idle instances are in the
future, the instance with the nearest schedule time is executed
next and its priority value is set to zero.
Otherwise, among the considered instances the instance with the
highest priority value is executed (it then necessarily has a
schedule time that is already in the past), its priority value set
to zero, and the priority values of all other considered instances
are incremented by one.
EXAMPLES:
while_idle.NST
STATUS:
Preliminary.
FILE
/local/homes/rhaschke/nst7/man/../o.linx86_64//../nstsrc/nst_stdr.c