Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
VPKS_v2_UKR_new.doc
Скачиваний:
21
Добавлен:
11.09.2019
Размер:
2.31 Mб
Скачать

2. Структури програмування

Прості послідовні процеси

Звичайно при вивченні нової мови програмування спочатку освоюється програма виводу на екран дисплея деякого повідомлення. В Оккам-оточенні екран термінала представляється спеціальним каналом виводу. Значення, які виводяться в цей канал, відображаються на екрані як символьні дані. Отже, вивід на екран повідомлення можна оформити у вигляді наступного фрагмента:

DEF prompt = TABLE [BYTE 13, 'O', 'c', 'c', 'a', 'm', '*'','s', '*s', 'r', 'a', 'z', 'o', 'r']:

SEQ i = [1 FOR prompt [BYTE 0]] screen !

string [BYTE i]

Нагадаємо, що в нульовому елементі масиву prompt [BYTE 0] зберігається число елементів масиву.

Процес виводу в канал деякого довільного рядка буває дуже корисний у роботі. Все різноманіття процесів, що виводять рядки з різними довжинами, можна представити у вигляді іменованого процесу для виводу масиву символів у деякий канал.

PRОС output.string(CHAN output, VALUE string []) =

  • вивід рядка в канал з ім'ям output

SEQ i = (1 FOR string [BYTE 0]]

output ! string [BYTE i]:

Записаний у цьому прикладі коментар підсумує поведінка іменованого процесу output.string.

Тепер для виводу нашого повідомлення на екран дисплея необхідно записати в програмі ім'я процесу output.string з фактичними параметрами

output.string(terminal.screen, "Occam razor")

Прості паралельні процеси

Існує найпростіша програма, корисна для практичних додатків. У цій програмі два паралельно працюючі процеси спілкуються один з одним по асинхронному каналу. Асинхронний зв'язок реалізується, звичайно, через буфер. Буфер - теж процес, він очікує певного значення із вхідного каналу, запам'ятовуючи його в локальній змінній, і наступним кроком алгоритм намагається вивести значення, що зберігається в локальній змінній, у певний канал виводу:

SEQ

buffer.in ? val

buffer.out ! val

Цей фрагмент можна узагальнити і ввести іменований процес, що буде копіювати дані з одного каналу в іншій з буферизацією одного значення:

PROC buffer (CHAN buffer.in, buffer.out) =

WHILE TRUE

VAR val:

SEQ

buffer.in ? val

buffer.out ! val:

У цьому процесі використовується конструктор WHILE, але на місці логічного виразу для з'ясування питання про наступне виконання тіла циклу існує ключове слово TRUE, що зображує в мові Оккам константу, що має значення булевої «істини». За допомогою послідовності ключових слів WHILE TRUE в Оккам-програмах записують нескінченні цикли.

За допомогою процесу buffer можна вирішити канонічну задачу паралельних обчислень - завдання асинхронного обміну даними між двома паралельними процесами: процесом-виробником і процесом- споживачем.

Розглянемо спочатку варіант нескінченно працюючого завдання (рис.1):

Рис. 1

PROC producer (CHAN output) =

CHAN keyboard AT 2:

WHILE TRUE

VAR char:

SEQ

keyboard ? char

output ! char:

PROC consumer (CHAN input) =

CHAN screen AT 1:

WHILE TRUE

VAR char:

SEQ

input ? char

screen ! char; -2:

PROC buffer (CHAN buffer.in, buffer.out) =

WHILE TRUE

VAR val:

SEQ

buffer.in ? val

buffer.out ! val:

CHAN char.from.producer, char.to.consumer:

PAR

producer (char.from.producer)

buffer (char.from.producer, char.to.consumer)

consumer (char.to.consumer)

Буферизація одного значення дозволяє процесу-виробникові працювати з випередженням процесу-споживача на одне значення (один такт), тому якщо при "миттєвій фотографії" потоку даних у цьому фрагменті процес-виробник обробляє n-те дане, то буфер буде містити (n - 1) -e дане, а процес-споживач використовує (n - 2) -е дане.

У цьому прикладі з'явилася конструкція

CHAN ім'я_каналу AT номер:

за допомогою якої в програмах оголошуються спеціальні канали для зв'язку із зовнішнім миром. Наприклад, оголошення

CHAN input AT 2:

жорстко закріплює канал з ім'ям input за клавіатурою термінала, а оголошення

CHAN output AT 1:

зв'язує канал з ім'ям output з екраном дисплею.

В іменованому процесі consumer використовується трохи незвичайний процес-примітив виводу:

screen ! char ; -2:

Помітимо, що вивід на екран дисплея сам по собі буферизується, а константа -2 змушує виводити недозаповнений буфер.

Для того щоб коректно закінчити паралельну програму, що складається з декількох паралельних процесів, необхідно по каналах, через які вони повідомляються один з одним, поширювати сигнал закінчення роботи всієї програми. Інакше, якщо просто якимось образом припинити один з паралельно працюючих і сполучених процесів, то через якийсь час цей, а потому і всі інші процеси перейдуть у стан очікування введення даних по своїх каналах. Програма не зможе далі працювати, тобто виникне дедлок.

Розглянемо модифікацію нашої програми, що коректно закінчується при наборі на клавіатурі термінала спеціального символу з кодом ASCII 13, що позначає повернення каретки. У цьому випадку програма повинна закінчитися після введення одного рядка тексту, код 13 буде служити "термінатором" для всіх паралельно працюючих процесів програми:

DEF eoln = 13:

PROC producer (CHAN output) =

VAR run:

CHAN keyboard AT 2:

SEQ

run := TRUE

WHILE run

VAR char:

SEQ

keyboard ? char

output ! char

IF

char = eoln

run := FALSE

char <> eoln

SKIP:

PROC consumer (CHAN Input) =

VAR run:

CHAN screen AT 1:

SEQ

run := TRUE

WHILE run

VAR char:

SEQ

input ? char

IF

char = eoln

run := FALSE

char <> eoln

screen ! char; -2:

PROC buffer (CHAN buffer.in, buffer.out) =

VAR run:

SEQ

run := TRUE

WHILE run

VAR val:

SEQ

buffer.in ? val

buffer.out! val

IF

val = eoln

run := FALSE

val <> eoln

SKIP:

CHAN char.from.producer, char.to.consumer:

PAR

producer (char.from.producer)

buffer(char.from.producer, char.to.consumer)

consumer (char.to.consumer)

Якщо є необхідність у буферизації більшої кількості значень, можна побудувати ланцюжок (конвеєр) буферів для одного значення, які будуть реалізовувати чергу з дисципліною FIFO:

DEF n = 100:

CHAN comms [n + 1]:

PAR

producer (comms [0])

PAR i = [0 FOR n]

buffer(comms[i], comms [i + 1])

consumer (comms[n])

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]