У меня была переписка с 08.03.2017 с Josef Templ по поводу пакета Coroutines - Co_, который я разработал и опубликовал в 2014 г
- на CPC:http://www.zinnamturm.eu/downloadsAC.htm#Co_
- на sourceforgehttp://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 BLACKBOXhttps://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