По старту программы исполняется единственная задача. Её номер равен 0, и изначально это задача общего времени, которой разрешен 1 запуск на task_yield(). Другие задачи не могут выполняться, пока задача номер 0 не выполнит task_yield().
Если задача номер 0 (высшего уровня) достигает конца главного файла, вся программа считается исполненной и останавливается, независимо от того, что другие задачи всё ещё могут быть активными.
Если диспетчер не находит активных задач, т.е. в программе не осталось задач, которые следует поставить вновь на выполнение (в плане нет даже задачи номер 0), он останавливает программу с кодом окончания 0, наподобие abort(0).
Пример:
-- Задача t1 будет выполнена до 10 раз подряд, прежде чем
-- другим задачам общего времени будет отдано управление. Если управление
-- требуется задаче реального времени, t1 потеряет управление в её пользу.
task_schedule(t1, 10)
-- Задача t2 будет выполняться некоторое время между 4-ой и 5-ой секундами,
-- наступившими после текущего момента. Если не изменить план для t2, она будет
-- запускаться через каждые 4..5 секунд и в дальнейшем.
task_schedule(t2, {4, 5})
См. также:
task_create, task_yield, task_suspend, task_suspend
task_self
Синтаксис:
a = task_self()
Описание:
Выдаёт номер текущей задачи.
Комментарии:
Этот номер может понадобиться, если в задаче возникла необходимость перепланировать, приостановить или прекратить саму себя.
Пример:
-- перепланировать себя
task_schedule(task_self(), {5.9, 6.0})
См. также:
task_create, task_schedule, task_yield, task_suspend
task_status
Синтаксис:
i2 = task_status(a)
Описание:
Выдаёт код состояния задачи. Значения кода могут быть 1 (активна), 0 (приостановлена) и -1 (задача не существует).
Комментарии:
В задаче может возникнуть необходимость знания состояния одной или более других задач, если требуется решить, как продолжать некоторую работу.
Величина кода состояния -1 показывает, что задача никогда не существовала либо задача завершилась естественным путём, либо была прекращена.
Пример:
integer s
s = task_status(tid)
if s = 1 then
puts(1, "АКТИВНА\n")
elsif s = 0 then
puts(1, "ПРИОСТАНОВЛЕНА\n")
else
puts(1, "НЕ СУЩЕСТВУЕТ\n")
end if
См. также:
task_list, task_create, task_schedule, task_suspend
task_suspend
Синтаксис:
task_suspend(a)
Описание:
Приостанавливает выполнение задачи номер a.
Комментарии:
Подача команды приостанавливает выполнение задачи номер a. Задача a не будет в дальнейшем выполняться, если для неё не будет снова подана команда task_schedule(). Номер a - это номер, который выдаёт функция task_create().
Любая задача может приостанавливать любую другую задачу. Если задача приостанавливает саму себя, остановка начнётся по вызову task_yield().
Пример:
-- приотановить задачу 15
task_suspend(15)
-- приостановить текущую задачу
task_suspend(task_self())
См. также:
task_create, task_schedule, task_self, task_yield
task_yield
Синтаксис:
task_yield()
Описание:
Передаёт управление задачами диспетчеру. Диспетчер может выбрать другую задачу для продолжения работы или, возможно, разрешить текущей задаче продолжить работу.
Комментарии:
В задачах должен быть предусмотрен периодический вызов task_yield(), чтобы другие задачи получали шанс быть решёнными. Только если в задаче подана команда task_yield(), диспетчер получит управление над задачами. Эта схема осуществления многозадачности известна как кооперативная многозадачность.
Задача может иметь вызовы task_yield() во многих различных местах её кода, и на любой глубине вызова подпрограмм.
Диспетчер будет использовать текущую величину {min, max} или оставшееся текущее число последовательных вызовов, определяя, когда следует вернуться к текущей задаче.
Когда управление возвращается в задачу, её выполнение продолжается с команды, которая следует за task_yield(). Стек вызова и все частные переменные останутся теми, какими они были перед вызовом task_yield(). Глобальные и местные переменные могут измениться при выполнении других задач.
Задачи должны пытаться вызывать task_yield() достаточно часто, чтобы не затруднять попадание задач реального времени в их временные окна и не блокировать задачи общего времени на слишком большие периоды времени. С другой стороны, на вызов task_yield() тратится некоторое время, и это время слегка больше, когда имеет место действительное переключение на другую задачу.
Задача должна избегать вызова task_yield(), когда она находится в процессе выполнения некоторой деликатной операции, требующей исключительного доступа к данным. В противном случае может возникнуть нечто вроде гонки между задачами, когда операция в одной задаче интерферируют с аналогичной операцией в другой. В некоторых случаях задаче может потребоваться маркировка данных как "запертых", чтобы предотвратить их встречную модификацию другой задачей. Правда, с кооперативной многозадачностью эти конкурентные вопросы составляют намного меньшую проблему, чем с вытесняющей, которая поддерживается другими языками.
Читать дальше