<<< BACK NEXT >>>

ВЫЗОВЫ БЛОКОВ КОМАНД И ИНИЦИАЦИЯ ПАРАЛЛЕЛЬНЫХ ВЫЧИСЛЕНИЙ

 Ниже приводятся основные операторы управления запуском (DO-запись).Форма 1 (запуск перечислением блоков с параметрами):
   DO [ SEQ | SYNCH | ASYNCH ] bl1,bl2,...,blk
                               [ WITH quant1,quant2,...,quantk ]
                               [ WITHIN med1,med2,...,medk ]

Форма 2 (запуск перечислением массивов):

   DO [ SEQ | SYNCH | ASYNCH ] [ ARRAY ] aname1, aname2,..., anameK
                               [ WITH quant1,quant2,...,quantk ]
                               [ WITHIN med1,med2,...,medk ]

   и обусловленного запуска для обеих форм:

   IF <условие> <DO-запись>

bl1,bl2,...,blk - список дескрипторов вызова блоков команд, имеющие следующие возможные формы:

<указатель блока >[( [ <параметр 1>, <параметр 2>,  .  .  . , <параметр N> ] ) ]

либо

(<указатель блока 1 > , <указатель блока 2 >,  .  .  . , <указатель блока K >)
             [( [ <параметр 1>, <параметр 2>,  .  .  . , <параметр N>  ] ) ]

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

В форме 2 anamei ( 1<= i <= K ) – имя переменной – массива, элементами которого являются структуры порожденного по описаниям в internal блоков или их прототипами.

   quant1,quant2,...,quantk - список квантов времени в миллисекундах, выделяемых на исполнение блока - перечень числовых значений.
   med1,med2,...,medk - список имен машин многомашинной ассоциации, на которой должны быть исполнены соответствующие блоки.

   Опция SEQ требует последовательного исполнения списка блоков команд, т.е. перечисленные в списке блоки запускаются последовательно; выполнение процедуры (блока), инициировавшей данный вызов, приостанавливается до тех пор, пока список не будет исчерпан. Опции квантования и распределения по компьютерам (или
процессорам) для вызова списка не действуют. Опция SYNCH определяет параллельное исполнение блоков с ожиданием в вызывающем(синхронный параллелизм).
   Опция ASYNCH определяет параллельное выполнение как вызываемых блоков, так и вызвавшего (асинхронный параллелизм). В этом случае возможно установить ожидание события завершения в нужном месте с помощью оператора

   WAIT <событие>

либо

   WAIT IsSynch()

(подробнее см. ниже).
   Для асинхронного вызова в определителе опции WITH должно указываться k+1 величин квантов времени, выделенных на каждую запускаемую процедуру; последим числом должна быть величина кванта, выделяемого для вызвавшего процесса.

   DO ASYNCH b1,...,bk WITH q1,...,qk+1

(qk+1 - квант времени для работы вызвавшего процесса).

Примеры:

             do Block1       ;* Пример 1

             do &var1( )     ;* Пример 2

********************       Пример 3      *******************

             do synch  Block1,   Block2(parm21, parm22),     =>
                 Block3( parm31, , parm33 ), block4

********************       Пример 4       *******************
   do asynch ( Block1, Block2, &var1 ) (parm1, parm2),         =>
                       Block3( parm31, , parm33 ) ,  =>
                       block4

*******************         Пример 5       *******************
   do SEQ Block1, Block2(parm1,  null , parm2), Block3

или

   do Block1, Block2(parm1,  null , parm2), Block3

   Первые два примера описывают т.н. простой вызов блоков: блок запускается, вызвавший его блок приостанавливает свое выполнения до завершения вызванного. причем во втором примере блок запускается через его указание в переменной.
   В третьем  примере осуществляется синхронный запуск блоков:  первый и четвертый блоки без параметров. В четвертом примере асинхронно запускаются блоки  Block1, Block2, &var1 (блок, адрес которого в переменной var1)  с общими параметрами parm1 и parm2, а также блок Block3 с параметрами и block4. Одновременно продолжает выполняться
вызвавший их блок.В последнем примере выполняется последовательный запуск перечисленных блоков.
   К уже исполняемым параллельным процессам, запущенным оператором DO, можно присоединить дополнительные процессы с помощью новой команды DO, т.е. всякий оператор DO, выполненный в ходе параллельного вычисления, добавляет в список параллельно выполняемых блоков новые.
   Кроме того, режим ASYNCH более весом, чем SYNCH. Это выражается в том, что если после инициации режима SYNCH будет выполняться

   DO ASYNCH . . .

то текущий режим будет изменен на ASYNCH, в то время как обратное не действует, т.е. вызов

   DO SYNCH  . . .

не приведет к изменению режима ASYNCH.

   Механизм вызовов базируется на стековом управлении: информация о вызвавшем блоке команд записывается в стек, а после возвращения в него удаляется. Возможны прямые способы управления стеком.Для обычного вызова блока в языке присутствует функция

   CallBlock( <указание блока>, <параметр 1> , . . . , <параметр N> )

где <указание блока> - это либо строка - имя блока, или адрес блока;
<параметр 1> - <параметр N>  - параметры для вызываемого блока.
   Возврат в вызвавший блок осуществляется по достижении конца блока или же оператором

   RETURN [<выражение>] [TO <имя блока>]

   Если фрагмент с TO опущен, то возврат осуществляется в вызвавший блок. В случае, если текущим (исполняемым) является MAIN, то осуществляется выход из программы. Если указан иной, чем вызвавший блок, то в стеке вызовов осуществляется поиск атрибутов указываемого блока. Если такие атрибуты существуют (возможно, их несколько), то возврат осуществляется по атрибутам последнего вызова. Поясним.
Пусть
   { a1, a2, ...,ai-1, b, ai+1,..., b,...,b,..., an} - текущее состояние стека
вызовов. Если в текущем блоке указан возврат в блок, атрибуты которого обозначены как b, то выбирается первый справа.

   RETURN [<выражение>] - возврат в вызвавший блок.

   Для параллельно запущенных процессов создается массив возвращаемых значений. Возвращаемое значение размещается в элемент массива, соответствующего номеру параллельно исполняемого блока. Т.е. в CAPER создается общее поле результатов различных вычислений.
   Получение возвращаемого значение должно осуществляться с помощью функции
RetValue( [ <номер процесса> ] ).
   . . .
   DO Block1( pVar1, pVar2 )
   if retValue() > 0
      . . .
   endif
   . . .
В данном случае применимо и традиционное:
   . . .
   var := Block1( pVar1, pVar2 )

DO SYNCH bL1, bL2( pVar11, pVar12 ), Block1( pVar21, pVar22 )
   lVar1 := RetValue( 2 ) + RetValue( 1 )
   if ( lVar1 := RetValue( 3 ) ) > 10
      . . .
   endif
*---------------------------------------
   Block Block1( fVar1, fVar2 )
     . . .
     Return pVar1+pVar2
     . . .
   EndBlock
*---------------------------------------

   Кроме приведенной формы возврата существует оператор обусловленного возврата:

   IF <выражение0> RETURN [<выражение1>] [TO <имя блока>]

   Безусловный возврат в операционную среду с прерыванием всех текущих процессов и закрытием всех файлов осуществляется по команде

   QUIT

Кроме того, виртуальной машиной будут выгружены из памяти все загруженные модули.
Кроме перечисленного, CAPER предоставляет возможность прямого управления стеком вызова процесса.

   EraseStack( <указание блока> [, <стиль> ] )

<указание блока>  - адрес или имя блока;
<стиль>           - 0 или 1  ( TO_LAST или TO_FIRST ).
Функция позволяет сбросить стек вызовов блоков до последнего вызова указываемого блока ( TO_LAST ) или до первого его вызова TO_FIRST.

   a1, a2, ..., B, aI, ... , B, ...
               F            L

При <стиль> TO_LAST стек сбрасывается до B, помеченного L, при TO_FIRST -
до B, помеченного F.

   BreakStack() - сбрасывает стек полностью.

<<< BACK NEXT >>>