Expand/Shrink

task_yield

Definition: task_yield()
Description: Yield control to the scheduler. The scheduler can then choose another task to run, or perhaps let the current task continue running.
pwa/p2js: Not supported.
Comments: Tasks should call task_yield() periodically so other that tasks have a chance to run.
Only when task_yield() is called, is there a way for the scheduler to take back control from a task.
This is known as cooperative multitasking.

A task can have calls to task_yield() in many different places in its code, and at any depth of subroutine call.
Note however there are significant restrictions for c_func/call_func/call_back/delete_routine/type-check, see technicalia.

The scheduler uses the current value of {min, max} or the current number of consecutive runs remaining, in determining when to return to the current task.

When control returns, execution continues with the statement that follows task_yield().
The call-stack and all private variables remain as they were when task_yield() was called.
Global and local variables may have changed, due to the execution of other tasks.

Tasks should try to call task_yield() often enough to avoid causing real-time tasks to miss their time window, and to avoid blocking time-shared tasks for an excessive period of time. On the other hand, there is a bit of overhead in calling task_yield(), and this overhead is slightly larger when an actual switch to a different task takes place.

A task should avoid calling task_yield() when it is in the middle of a delicate operation that requires exclusive access to some data. Otherwise a race-condition could occur, where one task might interfere with an operation being carried out by another task. In some cases a task might need to mark some data as "locked" or "unlocked" in order to prevent this possibility. With cooperative multitasking, these concurrency issues are much less of a problem than with preemptive multithreading.
Example 1:
-- this is how the main thread might wait for all tasks to complete
terminate_application = 1   -- tell threads to start shutting down, if appropriate
while active_tasks>0 do     -- (active_tasks is a manually maintained counter)
    task_yield()
    sleep(0.1)              -- (recommended if any real-time tasks are in use)
end while
abort(0)
Example 2:
-- an alternative to the above:
main_task_id = task_self()
task_suspend(main_task_id)
task_yield()
-- (nb: if no other task invokes task_schedule(main_task_id), control never returns)
Example Programs Both demo\rosetta\Generator_Exponential.exw and demo\rosetta\Same_Fringe.exw use task_yeild to implement a routine that can suspend itself mid-execution and later be resumed to obtain the next value, as many times as desired.
Implementation: See builtins\VM\pTask.e (an autoinclude) for details of the actual implementation.
See Also: task_create, task_schedule, task_suspend, task_self
Expand/Shrink