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

/amnt/loge/users/nistaff02/nistaff/rhaschke/nst7/man/../o.linux//../nstsrc/nst_stdr.c