Выбрать главу

Для задач общего времени увеличение аргумента x будет увеличивать процент времени процессора, отдаваемого для выбранной задачи, при уменьшении этого процента для других задач общего времени. При этом эффективность программы в целом возрастёт, так как каждое переключение задач само по себе требует некоторого небольщого времени. Вызов task_yield(), когда та же самая задача продолжает выполняться, занимает меньше времени. Тем не менее, данный приём не всегда применим, так как может блокировать выполнение других задач общего времени на длительные периоды времени. Имейте в виду, что задачи реального времени всегда имеют приоритет перед любым task_yield(), если достигнуто время их активации.

По старту программы исполняется единственная задача. Её номер равен 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(), когда она находится в процессе выполнения некоторой деликатной операции, требующей исключительного доступа к данным. В противном случае может возникнуть нечто вроде гонки между задачами, когда операция в одной задаче интерферируют с аналогичной операцией в другой. В некоторых случаях задаче может потребоваться маркировка данных как "запертых", чтобы предотвратить их встречную модификацию другой задачей. Правда, с кооперативной многозадачностью эти конкурентные вопросы составляют намного меньшую проблему, чем с вытесняющей, которая поддерживается другими языками.

Пример:

-- Из игры Language war.

-- Эта небольшая задача имитирует расходование запасов энергии

-- на корабле Euphoria и на его челноке.

-- Задача представляется "вечной" в бесконечном цикле,

-- но на самом деле это задача реального времени, которая вызывается

-- с периодом 1.7 - 1.8 секунды на протяжении всей игры.

-- Каждый раз при её вызове расходуется 3 или 13 единиц энергии.

global procedure task_life()

-- независимая задача: вычитание из запасов энергии

while TRUE do

if shuttle then

p_energy(-3)

else

p_energy(-13)

end if

task_yield()

end while

end procedure

См. также:

task_create, task_schedule, task_suspend task_suspend

text_color

Синтаксис:

include graphics.e