Подробнее про ObxActions против Co_ObxActions.
Изначальный пример ObxActions в BlackBox вызывает за один цикл Services.Action (период около 50 миллисекунд) процедуру
Код:
PROCEDURE Step (VAR cur, divisor: INTEGER; f: TextMappers.Formatter);
VAR end, sqrtCur: INTEGER;
BEGIN
end := divisor + stepSize;
sqrtCur := SHORT(ENTIER(Math.Sqrt(cur)));
WHILE (divisor <= sqrtCur) & (divisor < end) & (cur MOD divisor # 0) DO divisor := divisor + 2 END;
IF divisor > sqrtCur THEN (* cur is a prime *)
f.WriteInt(cur); f.WriteLn;
divisor := 3; cur := cur + 2
ELSIF divisor < end THEN (* cur is not a prime, test next one *)
divisor := 3; cur := cur + 2
ELSE (* time exhausted, continue test next time *)
END
END Step;
После одной итерации расчетов происходит выход из процедуры, чем завершается содержательная часть (a: PrimeAction) Do.
Пример с Co_ObxActions вызывается планировщиком Co_SchedTasks.
Код:
PROCEDURE Do (t: Ct.Task) ;
VAR a: PrimeAction; end, sqrtCur, n: INTEGER;
BEGIN
a := t(PrimeAction);
FOR n := 0 TO a.attempts-1 DO
a.current := 3; a.divisor := 3;
REPEAT
end := a.divisor + stepSize;
sqrtCur := SHORT(ENTIER(Math.Sqrt(a.current)));
WHILE (a.divisor <= sqrtCur) & (a.divisor < end) & (a.current MOD a.divisor # 0) DO
a.divisor := a.divisor + 2
END;
IF a.divisor > sqrtCur THEN (* cur is a prime *)
IF n = 0 THEN
a.f.WriteInt(a.current); a.f.WriteLn
END;
a.divisor := 3; a.current := a.current + 2
ELSIF a.divisor < end THEN (* cur is not a prime, test next one *)
a.divisor := 3; a.current := a.current + 2
END
UNTIL a.current > a.to;
Co.Yield
END;
Co.Stop
END Do;
Здесь после каждой итерации вызывается Co.Yield, после чего управление передается планировщику. Планировщик смотрит, есть ли время до следующего цикла. По умолчанию (load_pct - может быть изменено) фоновым задачам отводится до 40% процессорного времени. Если есть время 40% от времени цикла - шаг планировщика повторяется и вновь вызывается задача Do.
Что выяснилось? За время 9 сек на моем компьютере пример ObxActions выполняется 1 раз (Upper Bound= 256), а Co_ObxActions выполняется 400000 раз (Upper Bound= 256, N Attempts= 400000). Значит, фоновая задача в ObxActions использует имеющееся время неэффективно.
Иван Денисов писал(а):
А что тогда происходит во время срабатывания следующего цикла? Возврат в главную сопрограмму?
Каждый цикл Action вызывает планировщик Co_SchedTasks
Код:
PROCEDURE (a: Action) Do ();
BEGIN
IF a.s.enabled THEN
a.s.Step(a.s); Services.DoLater(a, a.s.p.interval)
END
END Do;
А Step планировщика передает управление сопрограммам и получает управление назад, когда те делают Co.Yield.
Info писал(а):
Правильно я понимаю, что это что-то вроде специального фонового Action'а, который добавляет опций управления очередью Экшенов сверх тех, что есть в ББ?
Один Action, на нем висит планировщик, он управляет очередью сопрограмм.