У меня была переписка с 08.03.2017 с Josef Templ по поводу пакета Coroutines - Co_, который я разработал и опубликовал в 2014 г
- на CPC:
http://www.zinnamturm.eu/downloadsAC.htm#Co_- на sourceforge
http://sourceforge.net/projects/ta1/files/co2.0/по пакетам лицензионных ограничений нет.
Далее 21.03 появилась заметка "adding Coroutines to BlackBox" в
https://forum.blackboxframework.org/viewtopic.php?f=41&t=610.
Сказано, вдохновленный пакетом Co_.
А, поскольку написать прямо в blackboxframework я не могу, я изложу свою позицию здесь, пусть читают по-русски (хорошо бы, Ивану Андреевичу любезно дать им ссылку на этот пост).
1-ADDING COROUTINES TO BLACKBOX
https://redmine.blackboxframework.org/issues/156- звучит неправильно, мой пакет давно добавлен. Другой разрабатывает Josef Templ. Если использует что-то из меня - замечательно.
Но нужно бы написать -
Josef Templ писал(а):
integration into Kernel services such as garbage collection, trap handling and trap cleaners
.
И нужно сделать поддержку со стороны ядра сборку мусора для локальных стеков и очистку трапов. Чтобы работало для всех пакетов. Кстати, есть еще и пакет сопрограмм Ермакова.
2-BASED ON WINDOWS FIBERS
Как справедливо замечено
Иван Денисов писал(а):
Your design is binding BlackBox to Windows OS forever
.
А у меня версия Co_ для BlackBox/XDS Windows/Linux.
И, между прочим, работает на 1 блоке Ростовской АЭС.
3-Есть 2 вида сопрограмм
http://wiki.c2.com/?CoRoutine:
1.Anonymous coroutines - переключаются планировщиком для кооперативной многозадачности (Cooperative Multitasking). Они не обмениваются между собой данными. Сопрограмма просто уступает управление командой Yield. А планировщик выбирает, на какую программу переключить.
2.Directed coroutines - Явно осуществляется переход. Используется в генераторах и проч по схеме Transfer - Yield. Как правило, обмениваются между собой данными.
В чем проблема? На рисунке co3.png показано, как переключаются 3 сопрограммы.
Process1 вызывает Process2, Process2 вызывает Process 3, Process 3 вызывает Process 1.
Эта схема работает только, когда процессы не обмениваются данными, т.е. для анонимных сопрограмм.
Для directed coroutines реентерабельность должна быть запрещена.
Правильная последовательность :
Process1(transfer)->Process2(transfer)->Process3(yield)->Process2(yield)->Process1
В пакете Co_ это все реализовано, там есть планировщик со своими примерами и примеры с вызовами одной сопрограммы из другой.
4-a rather complex programming interface
Josef Templ писал(а):
a rather complex programming interface
Я предпочитаю AS SIMPLE AS POSSIBLE, BUT NOT SIMPLER. Простота не за счет исгнорирования проблем.
Был мой пример с SameFringe Problem
Дагаев
Код:
IMPORT Ct := Co_Tasks, Co := Co_Routines, Log;
TYPE
Tree = POINTER TO TreeDesc;
TreeDesc = RECORD
name: ARRAY 16 OF CHAR;
left, right: Tree
END;
Traverse = POINTER TO TraverseDesc;
TraverseDesc = RECORD (Co.CoroutineDesc)
tree, leaf: Tree
END;
PROCEDURE NextTreeLeaves (trav: Traverse; tree: Tree);
BEGIN
IF (tree.left = NIL) & (tree.right = NIL) THEN
trav.leaf := tree;
Co.Yield
END;
IF tree.left # NIL THEN
NextTreeLeaves (trav, tree.left)
END;
IF tree.right # NIL THEN
NextTreeLeaves (trav, tree.right)
END;
END NextTreeLeaves;
PROCEDURE Do (t: Ct.Task);
VAR trav: Traverse;
BEGIN
trav := t(Traverse);
NextTreeLeaves(trav, trav.tree);
Co.Stop
END Do;
PROCEDURE Problem*;
VAR t1, t2, c1, c2: Tree; r1, r2: Traverse; same: BOOLEAN;
BEGIN
(* two trees are different, but have the same fringe: a, b, c *)
NEW(t1); NEW(c1); t1.left := c1; NEW(c2); c2.name := "a"; c1.left := c2; NEW(c2); c2.name := "b";
c1.right := c2; NEW(c1); t1.right := c1; NEW(c2); c2.name := "c"; c1.left := c2;
NEW(t2); NEW(c1); t2.left := c1; NEW(c2); c2.name := "a"; c1.left := c2; NEW(c2); c2.name := "b";
c1.right := c2; NEW(c1); t2.right := c1; NEW(c2); c1.left := c2;
NEW(c1); c1.name := "c"; c2.left := c1;
NEW(r1); r1.tree := t1;
NEW(r2); r2.tree := t2;
same := TRUE;
Co.InitCoroutine(r1, Do); Co.InitCoroutine(r2, Do);
r1.Start(r1); r2.Start(r2);
WHILE ~r1.eor & ~r2.eor & same DO
r1.Transfer(r1);
r2.Transfer(r2);
same := (r1.leaf.name$ = r2.leaf.name$)
END;
IF ~r1.eor OR ~r2.eor THEN same := FALSE END;
Log.String("tree1(a,b,c) vs tree2(a,b,c): The Same Fringe is"); Log.Bool(same); Log.Ln;
(* modify second, append 'd' *)
NEW(c2); c2.name := "d"; c1.right := c2;
same := TRUE;
Co.InitCoroutine(r1, Do); Co.InitCoroutine(r2, Do);
r1.Start(r1); r2.Start(r2);
WHILE ~r1.eor & ~r2.eor & same DO
r1.Transfer(r1);
r2.Transfer(r2);
same := (r1.leaf.name$ = r2.leaf.name$)
END;
IF ~r1.eor OR ~r2.eor THEN same := FALSE END;
Log.String("tree1(a,b,c) vs tree2(a,b,c,d) The Same Fringe is"); Log.Bool(same); Log.Ln;
END Problem;
Появился пример
J.Templ
https://redmine.blackboxframework.org/projects/blackbox/repository/diff?utf8=%E2%9C%93&rev=69c1383cadb025bd8eef4df48aab8fe1ac8bf0c0&rev_to=5ce6ea8c5090b35e4c93b5051e43a03634663ac9