Occam — мова паралельного програмування високого рівня, розроблена на початку 1980-х років групою вчених з Оксфорду під керівництвом Девіда Мея[en] за завданням англійської компанії INMOS Ltd. в рамках робіт зі створення трансп'ютерів. Названий на честь англійського філософа XIV століття Вільма Оккамського, а його сентенція, відома як бритва Оккама, є девізом проекту.

Між мовою Occam і трансп'ютерами існує безпосередній зв'язок: INMOS-трансп'ютери спроектовані так, щоб об'єкти і конструкції Occam реалізовувалися у їхній системі команд найкращим чином. Фактично, трансп'ютер є «кремнієвою реалізацією» мови Occam. Довгий час INMOS стверджувала, що трансп'ютерам не потрібна система програмування типу «Асемблер», так як її цілком замінює Occam.

Проте, Occam є типовою мовою високого рівня, синтаксично схожою на Паскаль та Сі.

В основі мови лежить так звана CPS (концепція взаємодіючих послідовних процесів), розроблена Ч. Хоаром. По суті, CSP — це формалізм для опису відповідної обчислювальної моделі, досить виразний, щоб на ньому можна було записувати і доводити теореми, досить потужний і однозначний, щоб бути мовою програмування (відомо кілька реалізацій). Згідно CSP, спочатку вводиться безліч елементарних подій (алфавіт), потім з них конструюються процеси, причому з тільки що описаних процесів можна будувати нові. Процеси, які виконуються паралельно, обмінюються інформацією, використовуючи безбуферний обмін інформацією типу «Рандеву» між парою процесів за допомогою спеціального об'єкта — каналу. При взаємодії той учасник обміну, який звернувся до каналу першим, чекає готовності партнера (точки рандеву); при настанні останньої ініціюється обмін. Використання загальної для декількох паралельних процесів пам'яті в CSP не допускається.

Базовим поняттям мови Occam є обчислювальний процес; основною характеристикою процесу є те, що він може бути розпочатий і завершений. У мові визначено кілька простих процесів: процес привласнення, процеси введення і виведення через канал (позначаються символами «?» і «!»), формальні процеси SKIP і STOP (перший завершується відразу ж, другий — ніколи), процеси читання таймера і таймерної затримки. Всі інші процеси можуть бути отримані ієрархічною побудовою. Для цієї мети Occam надає набір конструкторів процесів: SEQ (визначає процес послідовного виконання процесів), PAR (визначає процес паралельного виконання процесів), а також конструктор умовного процесу IF, циклічного процесу WHILE, процесу вибору процесів ALT. При цьому діє правило, згідно за яким процес типу SEQ і PAR вважається виконаним, коли завершені всі складові його процеси. Процеси можуть бути названі і викликані на ім'я з передачею параметрів. Процеси SEQ, PAR, IF і ALT можуть бути розмножені за допомогою реплікатору FOR. Процес ALT (як і PAR) додає в мову індетермінізм, так як вважається, що при одночасному виконанні декількох умов точно передбачити подальший хід подій неможливо.

  приклад:
  Мультиплексор, безкінечно читає з масиву каналів in[] і передає в загальний канал out,
  використовуючи змінну temp
     WHILE TRUE
       INT temp :
       ALT i=0 FOR N
         in[i] ? temp
           out ! temp
  приклад:
  Каскад мультиплексорів, які працюють одночасно.
  На вході — масив з M*N каналів in[], на виході — канал out.  
  Масив з M каналів ch[] використовується для зв'язку між мультиплексорами каскаду:
     PAR -- каскад паралельних мультиплексорів вводу
       PAR i=0 FOR M -- M паралельних мультиплексорів, які обробляють по N каналів з in[] кожний
         WHILE TRUE
           INT temp :
           ALT j=i*N FOR N
             in[j] ? temp
               ch[i] ! temp
       WHILE TRUE -- мультиплексор, який читає M каналів ch[]
         INT temp :
         ALT i=0 FOR M
           ch[i] ? temp
             out ! temp
  приклад:
  Процес буферизації вводу-виводу.
  Запуск процесу buffer( in, out, N) дозволяє каналу out відстати від каналу in 
  на N повідомлень, які будуть буферизовані всередині процесу buffer:
     PROC buffer( CHAN OF INT in, out, INT N)
       CHAN OF INT in.wait, out.wait :
       INT n : -- лічильник буферизованих значень
       [N]INT buff :
       SEQ
         n:=0
         PAR—input
           INT i, any: -- i — вказівка запису в буфер
           SEQ
             i:=0
             WHILE TRUE
               SEQ
                 WHILE n<(N-1)
                   SEQ
                     in ? buff[i]
                     n:=n+1
                     IF
                       n=1
                         out.wait ! any
                       TRUE
                         SKIP
                     i:=(i+1) MOD N
                 in.wait ? any—output
           INT j, any: -- j — вказівка читання з буферу
           SEQ
             j:=0
             WHILE TRUE
               SEQ
                 out.wait ? any
                 WHILE n>0
                   SEQ
                     out ! buff[j]
                     n:=n-1
                     IF
                       n=(N-2)
                         in.wait ! any
                       TRUE
                         SKIP
                     j:=(j+1) MOD N
     :

Вивчаючи приклади, слід мати на увазі, що символ «два мінуси» — означає початок коментаря до кінця рядка, а символ «крапка» може бути в Occam частиною ідентифікатора і не несе ніякого спеціального навантаження. Символ «двокрапка»: має значення «кінець опису». Occam чутлива до заголовних / рядкових букв у ідентифікаторах.

Цікавою особливістю мови Occam є включення індентації (відступів, «драбинки») в його синтаксис. Цей популярний і вельми виразний засіб виділення структури в Occam є єдиним способом вказівки області дії конструкторів. В ряду безумовних переваг такого рішення можна назвати зменшення кількості службових символів при записі конструкції (відпадає необхідність в словах типу BEGIN-END, або фігурних дужках) і стандартизація оформлення текстів, що підвищує їх читабельність.

  Приклад важливості «драбинки»:
    SEQ
      proc1()
      PAR
        proc21()
        proc22()
      proc3()
  спершу тут буде виконаний процес proc1, потім буде паралельно виконуватися proc21 та proc22, 
  і після закінчення найбільш тривалого з них починається proc3. Якщо змістити виклик proc3 
 на рівень вправо, то proc3 починається одночасно з proc21 і proc22:
    SEQ
      proc1()
      PAR
        proc21()
        proc22()
        proc3()


Зміст

Версії та реалізаціїРедагувати

Офіційно у складі TDS (Transputer Development System), компанією INMOS Ltd. були випущені реалізації Occam 1.0, Occam 2.0 і Occam 2.1. Після покупки компанії і згортання розробок по трансп'ютерному проекту, розробниками Occam була опублікована специфікація Occam 3. Пізніше група ентузіастів здійснила реалізацію мови Occam 2.5, яка представляла собою Occam 2.1 з деякими нововведеннями з Occam 3. Останній же в повному обсязі реалізований не був.

Розвиток мови Occam ішов у бік додавання нових типів даних, високорівневих понять і засобів, що полегшують програмування.

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

Відомі також бібліотеки, які реалізують примітиви базової для Occam концепції CSP, що дозволяє програмувати в стилі Occam на інших мовах.

Дивитись такожРедагувати

ЛітератураРедагувати

  • Джоунз Г. Програмування на мові «Occam»

ПосиланняРедагувати