<<< BACK NEXT >>>

УПРАВЛЕНИЕ ПАРАЛЛЕЛЬНЫМИ ПРОЦЕССАМИ

Параллельные процессы в CAPER обеспечены разнообразными средствами управления и взаимного воздействия. Помимо тех очевидных средств, которые возможно организовать с помощью общих переменных и которые будут рассмотрены далее в примерах, имеются прямые средства воздействия на ход параллельных процессов.
   В первую очередь - это возможности выборочной приостановки и деактивация параллельных процессов.
   Временная приостановка процессов осуществляется оператором

   STOP <номер процесса 1>, <номер процесса 2>,  . . . , <номер процесса N>

или функцией

   StopProcess( <номер процесса 1>, <номер процесса 2>, . . . ,
                <номер процесса N> )

где <номер процесса i> - число – числовой идентификатор параллельно запущенного процесса.
   Все процессы с перечисленными номерами останавливаются до того момента, пока один из параллельно работающих процессов не восстановит их активность командой

   ACTIVATE <номер процесса 1>, <номер процесса 2>,  . . . , <номер процесса N>

или функцией

   ActivateProc( [{ <номер процесса > } ] ), где <номер потока> - число.

   Функция активизирует приостановленные ранее параллельные процессы; если параметры отсутствуют, то активизируются все параллельные ветки.Остановленные процессы могут и не возобновиться. Если завершат работу все
остальные, т.е. восстановление некому будет осуществлять, то машиной языка будет удалена вся информация, связанная с этими процессами, параметры, локальные переменные.Функция

   BreakProc( <номер процесса 1>, <номер процесса 2>,  . . . ,
              <номер процесса N> )

осуществляет выборочное принудительное завершение процессов.Полное принудительное завершение параллельных процессов осуществляется командой

   PARABREAK [ TO  <номер процесса> ]

   Данный оператор для синхронного и асинхронного режимов ведет себя по разному:
PARABREAK в асинхронном режиме прерываются все процессы, за исключением вызвавшего. Однако, здесь существует опасность - вызвавший процесс может быть уже завершен. В этом случае возникнет внутреннее программное прерывание по ошибке.
   PARABREAK TO  <номер процесса> прервет все параллельные процессы, а управление будет передано процессу с указываемым номером; при этом и здесь возможна та же ошибка "неживого" процесса; реакция виртуальной машины CAPER та же - будет вызвана внутренняя ошибка.
   Функция ParaBreak( ) прерывает параллельные процессы. Для синхронно вызванных процессов возврат осуществляется в вызвавший блок, для асинхронно вызванных процессов вычисление прерывается и осуществляется выход в систему. Для выхода в асинхронных процессах в нужный блок необходимо использовать команду
PARABREAK [ TO  <номер процесса> ]

Пример:
  do synch bL1( p1), bL2, bL3( p31, p32, p33 )
  LVar1 := var1 + var2
    . . .
  block bL2
    . . .
*    Здесь параллельный процесс будет прерван =>
     и следующей командой будет первая после DO SYNCH
    parabreak
  endblock

В то же время

   do asynch bL1( p1), bL2, bL3( p31, p32, p33 )
   while (LVar1 := var1 + var2) < var3
     . . .
   endw
   . . .

   block bL2
     . . .
*   Здесь параллельный процесс будет прерван =>
    и следующей командой будет команда из bL3
    parabreak  to 3
    . . .
   endblock

   block bL3( fp31, fp32, fp33 )
      . . .
   endblock
*---------------------------------

   В данном примере в bL2 асинхронный параллельный процесс прерывается, машина CAPER переводится в режим последовательного выполнения программы, активным остается bL3.

   do asynch bL1( p1 ), bL2, bL3( p31, p32, p33 )
   . . .

* Если выполнено условие, останавливаем два процесса
   if PublVar1 > var2
      StopProcess( 1, 2 )
   endif

   CAPER позволяет контролировать ход управления параллельными вычислениями с помощью вызова блока команд в момент переключения с одного параллельного процесса на другой. В вызванном блоке можно переопределить схему выполнения параллельных процессов.
   SetNext([<имя блока>]) - эквивалент SET NEXT в CAPER II - назначает блок,
вызываемый в момент переключения с одной параллельной ветви на другую.
   Если параметр отсутствует, то назначение снимается. Кроме того,

   FreezeNext() "замораживает" запуск Next-блока, а
   DefrNext() "размораживает" Next-блок.

   NEXT-блоки должны быть откомпилированы в режиме flow, ибо в противном случае после вызова такого блока и выполнения его первой команды виртуальный процессор попытается переключить параллельную ветвь и вновь вызовет NEXT-блок, и т.д., что приведет к забиванию стека вызовов.
   CAPER не контролирует стиль компиляции, а потому формально использование
блока с разделителем команд не запрещено и может быть указано. Однако последствия такого использования лежат на программисте.
   Определение номера текущего процесса осуществляется с помощью функции
   CurrParall()
   ParaCount() - возвращает число - количество параллельных процессов; в последовательном режиме возвращается 0.
   Принудительное переключение на процесс с определенным номером может быть осуществлен с помощью команды

   PASS [ TO <арифметическое выражение> ]

Если просто PASS, то управление передается очередному по порядку параллельному процессу. Если указан номер процесса - число, как значение арифметическоговыражения, - то машина CAPER переключит на параллельную ветвь с указанным номером.

С помощью функции

   SetQuant( <квант>, <номер процесса> [ {, <номер процесса i>} ])

можно в ходе вычислений изменять кванты времени процессов.
<квант>   - число - квант времени, который будет установлен процессу(ам) с номером (номерами) <номер процесса> ( <номер процесса i> )
<номер процесса> - число - номер параллельного процесса.

АДРЕСОВАНИЕ И ИСПОЛНЕНИЕ ОТДЕЛЬНЫХ КОМАНД

  

CAPER позволяет адресовать отдельные команды блоков. С этой возможностью связаны несколько дополнительных нетрадиционных средств управления ходом вычислений и выполнения команд. Эти средства обеспечены, в основном, функциями среды и методами компиляции.

Address() возвращает указание (адрес) команды, в которой присутствует данная функция.

ElementCnt( <указание блока> ) - возвращает количество элементов в блоке;если это блок команд, то количество команд блока, если блок данных, то количество данных блока, если блок типа TEXT, то количество строк.

GetAddr( <имя блока> ) - возвращает указание на начало блока.

GetElement( <указание блока>, <номер элемента> ) - возвращает адрес элемента блока или сам элемент; <указание блока> - символическое имя блока или указатель блока.

см. в  "Динамическая компиляция и загрузка"

<<< BACK NEXT >>>