Occam | |
Data da primeira versão | 1983 |
---|---|
Paradigma | Programação simultânea , computação distribuída , imperativo |
Desenvolvedor | Inmos |
Última versão | 2.1 (1988) |
Influenciado por | Comunicação de processos sequenciais |
A linguagem de programação Occam é uma linguagem de programação adaptada à arquitetura paralela, que surgiu em 1983. Foi desenvolvida pela Inmos para a programação de suas arquiteturas paralelas de Transputer , mas também foi portada para outras plataformas.
O nome é uma homenagem a Guilherme de Occam (às vezes soletrado Ockham) e ao princípio metodológico da navalha de Occam .
A linguagem Occam é uma linguagem procedural que oferece, além da execução de instruções sequencialmente (com SEQ), a execução de instruções em paralelo (com PAR) e até mesmo o “paralelismo assíncrono” de processos (com ALT) para um não execução determinística de um de muitos. A execução no PAR dos processos é feita com nomeações, como na Ada .
Occam também contém as "ordens guardadas" de Edsger Dijkstra : um processo só é iniciado se o valor de sua guarda, avaliado pelo sistema, for verdadeiro.
O Transputer Development System (TDS) da Inmos foi a ferramenta de desenvolvimento clássica para esta linguagem, mas era possível usar Parallel C ou outras ferramentas. O editor TDS permitiu o dobramento de código , o que foi muito inovador.
Em Occam, o recuo é significativo, o que evita os marcadores de início e fim de blocos comuns a outras linguagens herdadas de Pascal e C (início ... fim, {...}, loop ... endloop etc. ). Uma expressão é encerrada por um fim de linha. Várias expressões podem ser agrupadas em um bloco onde todas as linhas começam no mesmo recuo.
A comunicação entre processos paralelos é feita com "canais" definidos pela expressão "CHAN OF". Esses canais são implementados pelos links bidirecionais seriais rápidos (2 Mb / s, 4 links / Transputer, comunicação independente da CPU). Um processo envia dados pelo canal com "!" enquanto outro processo recebe os dados com "?", transmissão e recepção sendo síncronas:
keyboard ? c screen ! cSEQ apresenta uma lista de expressões que são avaliadas em sequência, uma após a outra. Exemplo:
SEQ x := x + 1 y := x * xPAR anuncia uma lista de expressões que provavelmente serão avaliadas simultaneamente. Exemplo:
PAR p() q()ALT indica uma lista de declarações mantidas . Os protetores são combinações de condições binárias e entrada no canal. Uma alternativa entre aqueles cujas condições são verdadeiras e cujos canais de entrada estão prontos, é executada. Exemplo:
ALT count1 < 100 & c1 ? data SEQ count1 := count1 + 1 merged ! data count2 < 100 & c2 ? data SEQ count2 := count2 + 1 merged ! data status ? request SEQ out ! count1 out ! count2Este exemplo lerá os dados dos canais "c1" e "c2" (se estiverem prontos) e os mesclará em um único canal de saída "mesclado". Se o contador countN atingir 100, a leitura do canal N será desabilitada. Uma solicitação sobre o estado do canal será respondida pelos dois contadores.
Alguns exemplos reais de código
PROC Passe1 ( CHAN OF ANY FromKeyboard, CHAN OF INT FromServer, CHAN OF ANY ToServer, CHAN OF ANY FromNetwork, ToNetwork, []CHAN OF Process FromMenu, CHAN OF FilerProtocol FromFiler, ToFiler, []INT UserWindow, SystemWindow, []INT ConfigData, freespace, VAL []BYTE parnomfic, parNumVersion, FicSorties, INT FicSortiesPtr ) -- Constantes de configuration disque VAL WrkExt IS ".CPS": VAL OutExt IS ".LIE": VAL IntExt IS ".$$$": VAL MaxCompressedRecordSize IS 45: -- taille avec compression CGA !!! VAL kAccesSequentiel IS TRUE: VAL theta1 IS 1.618 (REAL32): -- Constantes estimees VAL MaxTailleZone IS 9111833: VAL MaxVilles2 IS INT ROUND ((REAL32 TRUNC MaxVilles)*theta1): -- Variables [ReadBufferSize]BYTE MyReadBuffer: INT FicPos, FicSize: -- position dans, et nombre d'octets du, fichier [80]BYTE FicRes1, FicInt: -- Fonctions BOOL FUNCTION EndOfFile() IS ( (FicPos+MyReadPtr) >= FicSize ) : BOOL FUNCTION NotFini() IS ( (Result=0) AND (NOT EndOfFile()) ) : PROC Erreur ( VAL []BYTE par ) [82]BYTE loc: --BOOL poub: --INT len: SEQ --len:=82 --InitTabByte(loc,' ') [loc FROM 0 FOR (SIZE par)]:=par [loc FROM (SIZE par) FOR 2]:="*c*n" --delete.string(len,loc,(SIZE par) + 2,81 - (SIZE par),poub) WriteInTextWindow(ToServer,SystemWindow,[loc FROM 0 FOR (SIZE par) + 2])) -- previously UserWindowOutro exemplo :
IF sgf.res <> 0 SKIP TRUE IF compare.strings (ThfareKey, "99999999") <> 0 SEQ ThfareKeyInt := AtoI (ThfareKey) ThfareOffsets [ThfareKeyInt] := Offset TRUE SKIPExemplo de um multiplexador de canal:
WHILE TRUE VAR x; SEQ ALT c1 ? x c2 ? x c3 ? x