Upload
others
View
0
Download
0
Embed Size (px)
Citation preview
Introdução à programação em Ada 2005
Luís Miguel Pinho
Instituto Superior de Engenharia do Porto
Outubro de 2006
Introdução à programação em Ada 2005 Pág. 1
Luís Miguel Pinho – Instituto Superior de Engenharia do Porto Outubro de 2006
Índice
ÍNDICE.......................................................................................................................................................... 1
1. BREVES NOTAS...................................................................................................................................... 2
2. TIPOS DE DADOS................................................................................................................................... 4
3. OPERADORES......................................................................................................................................... 8
4. BLOCOS.................................................................................................................................................... 9
5. DECISÕES .............................................................................................................................................. 10
6. CICLOS................................................................................................................................................... 12
7. SUBPROGRAMAS ................................................................................................................................ 14
8. EXCEPÇÕES.......................................................................................................................................... 17
9. ESTRUTURA DE PROGRAMAS ........................................................................................................ 19
10. ENTRADA E SAÍDA............................................................................................................................ 22
11. MODELO DE CONCORRÊNCIA ..................................................................................................... 25
12. TAREFAS.............................................................................................................................................. 27
13. RENDEZVOUS..................................................................................................................................... 31
14. RELÓGIOS E TEMPORIZADORES ................................................................................................ 35
15. ATRASOS ............................................................................................................................................. 36
16. SYNCHRONOUS/ASYNCHRONOUS TASK CONTROL.............................................................. 38
17. INTERFACES....................................................................................................................................... 39
18. O PERFIL RAVENSCAR.................................................................................................................... 40
19. BIBLIOGRAFIA E RECURSOS ONLINE........................................................................................ 46
Introdução à programação em Ada 2005 Pág. 2
Luís Miguel Pinho – Instituto Superior de Engenharia do Porto Outubro de 2006
1. Breves notas
- Em 1973 o Departamento de Defesa Norte-Americano (DoD), recenseou 450 linguagens diferentes.
- Da avaliação das linguagens existentes em 1976 contra um conjunto de requisitos encontrados resultou:
- Nenhuma cumpria os requisitos
- Uma única linguagem era desejável
- O desenvolvimento era possível e devia começar de uma linguagem existente, sendo as recomendadas: Pascal, PL/I e ALGOL 68 (note-se a ausência do C)
- Foi escolhida a linguagem Pascal
- Em 1983 foi normalizada a linguagem Ada, verificando-se, no entanto, alguma desilusão com o seu suporte a Sistemas de Tempo Real.
- A linguagem não incorporava alguns dos avanços da altura em termos de escalonamento de Sistemas de Tempo Real.
- Portanto, em 1995 a primeira revisão da linguagem foi ao encontro das críticas e foi normalizada a linguagem Ada 95.
- Foi a primeira linguagem normalizada com suporte a orientado a objectos e sistemas de tempo-real
- Em 2000 iniciaram-se os trabalho de uma nova revisão da linguagem para incorporar avanços em diversas áreas (principalmente OO e STR)
- Suporte ao perfil Ravenscar (eficiência, simplicidade e previsibilidade), a prioridades dinâmicas e hierárquicas, interfaces
- Embora o nome seja Ada 2005, não é uma nova norma mas sim um “Amendment” (Ada 95 Amendment 1).
- O nome da linguagem é uma homenagem a Ada Lovelace (filha de Lord Byron), que foi assistente de Charles Babbage, o homem que inventou o primeiro computador (computador mecânico).
- Existe uma certa celeuma se foi Ada Lovelace ou Charles Babbage a primeira pessoa programadora da história. No entanto, Ada Lovelace foi de certeza a primeira mulher programadora da história.
- A norma (ISO/ANSI) impõe um núcleo da linguagem, mais um conjunto de Anexos especializados (Sistemas de Tempo Real, Sistemas Distribuídos, Sistemas de Informação, etc.).
- Os anexos definem bibliotecas e características de implementação, não acrescentam sintaxe nem vocabulário)
- Qualquer compilador de Ada tem que ser validado por empresas certificadas, tendo que cumprir a norma, mas podendo não cumprir certos anexos.
- A linguagem especifica também o seu próprio executivo, permitindo utilização mesmo sem Sistema Operativo.
Introdução à programação em Ada 2005 Pág. 3
Luís Miguel Pinho – Instituto Superior de Engenharia do Porto Outubro de 2006
- O compilador GNAT é talvez compilador mais utilizado (GNAT significa GNAT - não é um acrónimo)
- É de graça
- Existe para várias plataformas (Windows, Linux, etc..)
- É bastante eficiente (o backend é o GCC)
- Os identificadores podem conter letras, dígitos, ou o caracter “underscore” ( ‘_’ )
- Não podem começar por dígitos
- Podem ter palavras acentuadas
- Não existe distinção entre maiúsculas e minusculas
- If é igual a if e igual a IF
- Os números podem ter o caracter ‘_’, para ajudar a leitura
- Por exemplo 1234567 pode ser representado 1_234_567
- Os comentários começam com -- e são até ao final da linha
- Todas as instruções têm que levar ponto-e-vírgula (;) no fim
- Várias instruções podem vir na mesma linha, desde que separadas por ;
- Não há diferença entre um espaço, ou 20 espaços, ou um fim de linha
Nota: A partir deste momento a palavra Ada será utilizada para referir-se à norma de 1995, com os acrescentos de 2005. Se necessário, quando se referir à norma de 1983, será utilizado Ada 83 e a de 1995 será utilizada Ada 95.
Introdução à programação em Ada 2005 Pág. 4
Luís Miguel Pinho – Instituto Superior de Engenharia do Porto Outubro de 2006
2. Tipos de dados
- Um tipo de dados é um conjunto de valores com um conjunto de operações primitivas associadas
- Pode-se criar um novo tipo
- Pode-se criar um novo tipo derivado de outro
- O novo tipo “herda” as operações do outro
- Mas os tipos são completamente independentes
• Por exemplo não se pode comparar varáveis de um com variáveis do outro
- Pode-se criar um subtipo
- O subtipo pode ser utilizado conjuntamente com o Pai
• Mas há restrições
• Geralmente é utilizado para efectuar restrições de gama ou precisão
- Tipos discretos
- Enumerados:
- Boolean (predefinido)
- Character (predefinido) -> não é um inteiro, mas sim uma enumeração
- type Modo is (Manual, Automatico);
- type All_Days is (Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday);
- subtype Week_Days is All_Days range Monday .. Friday;
- Inteiros com sinal
- Integer (predefinido)
- type Index is range 1..10;
- Inteiros modulares
- Ada não tem inteiros sem sinal, pois facilmente se pode criar um com o range
- Ada tem os chamados tipos modulares em que se especifica o valor máximo, e que fazem “wrap” automaticamente
- type Byte is mod 256;
• Qualquer valor do tipo Byte vai de 0 a 255 ( wrap: 255 + 1 dá 0, tal como 0 - 1 dá 255)
- Tipos Reais
- Vírgula flutuante
- Float (predefinido)
- type Length is digits 5 range 0.0 .. 100.0;
- Vírgula Fixa
- type Voltage is delta 0.125 range 0.0 .. 5.25;
- type Money is delta 0.01 digits 15;
Introdução à programação em Ada 2005 Pág. 5
Luís Miguel Pinho – Instituto Superior de Engenharia do Porto Outubro de 2006
- Ada é uma linguagem fortemente tipificada
- Significa que não é flexível como o C/C++
- Mas é muito mais seguro
- Não se pode usar valores de um tipo em operações de outro tipo sem efectuar uma conversão de tipo explícita
- Regras para subtipos são mais relaxadas
- Exemplos:
I: Integer := 2;
F: Float := 1.2;
-- ...
F:= F * I; -- incorrecto, tem que ser:
F := F * Float(I);
F: Float := 1; -- é incorrecto, tem que ser:
F. Float := 1.0; -- ou
F. Float := Float(1);
type Int is new Integer;
A: Integer;
B: Int;
-- …
A := B; -- incorrecto, tem que ser
A := Integer(B);
subtype Int is Integer range 1..10;
A: Integer;
B: Int;
-- …
A := B; -- não há problema
B := A; -- pode dar excepção, se A estiver -- fora da gama de valores -- de Int (1 .. 10)
- Tipos Compostos
- Arrays
- String (predefinido)
- type Matrix is array (1 .. 4, 1 .. 4) of Integer;
- Não há índice obrigatório para o início do Array (estilo o 0 em C)
- Pode-se usar others para referenciar os restantes elementos de um array
- Exemplo:
S: String(1..10);
S1: String(2..6);
M: Matrix;
-- ...
S := “1234567890”;
S1 := S(5..9); -- Desde que o número de elementos bata certo
M := ((1,2,3,4),(2,3,4,5),(3,4,5,6),(4,5,6,7));
M(1,2) := 3;
S1(3) := ‘X’;
S := (1 => ‘a’ , 5 => ‘z’, others => ‘0’);
Introdução à programação em Ada 2005 Pág. 6
Luís Miguel Pinho – Instituto Superior de Engenharia do Porto Outubro de 2006
- Outro exemplo:
type Teacher is (Pinho, Tovar);
type Module is ( introduction, scheduling, languages,
dist_scheduling, fault_tolerance, development);
type Modules is array (Module) of Teacher;
STR: Modules;
-- …
STR := (languages => Pinho, development => Pinho,
fault_tolerance => Pinho , others => Tovar);
- Records (estruturas)
type Module is record
Prof: Teacher;
Duration: Positive;
end record;
M3: Module;
-- …
M3.Prof := Pinho;
M3 := (Pinho, 3);
M3 := (Duration => 3 , Prof => Pinho);
- Tipos de acesso
- Parecidos com apontadores (mas não são como os apontadores do C/C++ – não são inteiros)
- As variáveis a que se podem aceder têm que ser criadas dinamicamente
- Utiliza-se o . (ponto) tal como se não fosse tipo de acesso
- Excepto na atribuição do record todo de uma vez, em que se usa o .all
type Module is record
Prof: Teacher;
Duration: Positive;
end record;
type Access_Module is access Module;
access_M2 : Access_Module := new Module;
-- …
access_M2.Prof := Tovar;
access_M2.all := (Duration => 2 , Prof => Tovar);
Introdução à programação em Ada 2005 Pág. 7
Luís Miguel Pinho – Instituto Superior de Engenharia do Porto Outubro de 2006
- Atributos
- Certos tipos têm atributos que podem ser utilizados para obter informação sobre o tipo
- Os atributos são referenciados através do caracter plica (‘)
- Atributos existentes que podem ser aplicados a tipos e variáveis
- Size (tamanho do tipo em bits)
- Length (tamanho do tipo em elementos - só para arrays)
- Range (gama - só para tipos discretos, reais e arrays)
– Este é interessante mas veremos apenas nos ciclos
- Atributos existentes que apenas podem ser aplicados ao tipo
- First(primeiro elemento - só para tipos discretos, reais e arrays)
- Last (último elemento - só para tipos discretos, reais e arrays)
- Pred (elemento anterior - só para enumerações)
- Succ (próximo elemento - só para enumerações)
- Val (Valor numa determinada posição - só para enumerações)
- Pos (Posição de um determinado valor - só para enumerações)
I: Positive;
type String_10 is new String(1..10);
S: String(1..10);
-- …
I := Positive’First; -- I fica com 1
I := Integer’Size; -- I fica com 32
I:= S’Length; -- I fica com 10
I := String_10’Size; -- I fica com
-- 10*8 = 80
type All_Days is (Monday, Tuesday, Wednesday,
Thursday, Friday, Saturday, Sunday);
subtype Week_Days is All_Days
range Monday .. Friday;
subtype Weekend is All_Days
range Saturday .. Sunday;
-- …
All_Days'Succ(Monday) = Tuesday
All_Days'Pred(Tuesday) = Monday
All_Days'Val(0) = Monday
All_Days'First = Monday
All_Days'Val(2) = Wednesday
All_Days'Last = Sunday
All_Days'Succ(All_Days'Pred(Tuesday)) = Tuesday
Introdução à programação em Ada 2005 Pág. 8
Luís Miguel Pinho – Instituto Superior de Engenharia do Porto Outubro de 2006
3. Operadores
Nome Símbolo Exemplo
Atribuição := A := B
Aritméticos
Módulo Divisão mod B := A mod 2 Resto Divisão rem B := A rem 2 Valor absoluto abs B := abs A Exponenciação ** A := 2**8 Multiplicação * B := A * 2 Divisão / B := A / 2 Soma + B := A + 2 Subtracção - B := A – 2 Sinal positivo + A := + B Sinal negativo - A := - B;
Relacionais
Igualdade = if A = 3 Diferença /= if A /= 3 Maior > if A > 3 Menor < if A < 3 Maior ou Igual >= if A >= 3 Menor ou Igual <= if A <= 3
Lógicos
E lógico and if A>1 and B<2 and then if A>1 and then B<2 Ou lógico or if A>1 or B<2 or else if A>1 or else B<2 Ou lógico exclusivo xor if A>1 xor B<2 Negação not if A and not B
Outros
Pertença in if A in 1 .. 20 Concatenação & S := “A” & “BCD” Gama de valores .. 1 .. 10
Introdução à programação em Ada 2005 Pág. 9
Luís Miguel Pinho – Instituto Superior de Engenharia do Porto Outubro de 2006
4. Blocos
- Blocos de instruções
- É possível definir em qualquer parte um bloco de instruções, que contém uma zona de declarações própria
bloco ::= [identificador :]
[declare
{declarações}]
begin
instruções;
end [identificador];
- Exemplos:
declare
F: Float; -- F é local ao bloco
begin
F := Obtem_valor();
F1 := F * 2.5; -- F1 vem de fora do bloco
end; -- F deixa de existir aqui
bloco_exterior: -- cada bloco pode ser identificado
declare
F: Float; -- F é local ao bloco exterior
begin
F := Obtem_valor();
bloco_interior:
declare
F2: Float := 3.0; -- F2 é local ao bloco interior
begin
F1 := F * F2; -- F1 vem de fora do bloco
end bloco_interior;
F1 := F1 + F2 * 2.0; -- Erro: F2 já não existe aqui
end bloco_exterior; -- F deixa de existir aqui
Introdução à programação em Ada 2005 Pág. 10
Luís Miguel Pinho – Instituto Superior de Engenharia do Porto Outubro de 2006
5. Decisões
- Decisão se
Decisão-if ::=
if expressão-booleana then
instruções;
{elsif expressão-booleana then
instruções;}
[else
instruções;]
end if;
- Exemplos
if T <= 100.0 then
P := Max_ Power;
elsif T >= 180.0 then
P := 0. 0;
T := 180.0;
else
P := Control( R, t);
end if;
if estudei = true and then exame = facil then
Passei;
Festejar;
else
Estou_ca_para_o_ano;
end if;
- Nota: não se podem fazer atribuições dentro dos testes, só se pode ter expressões que dêem true ou false
estudei : Integer := 1;
if estudei and then exame = facil then -- errado, estudei não é booleano
Passei;
Festejar;
else
Estou_ca_para_o_ano;
end if;
Introdução à programação em Ada 2005 Pág. 11
Luís Miguel Pinho – Instituto Superior de Engenharia do Porto Outubro de 2006
- Decisão caso
decisão-case ::=
case expressão-discreta is
alternativa
{alternativa}
end case;
alternativa ::= when lista => înstruções;
lista ::= opção {| opção}
opção::= expressão | intervalo | others
- Exemplo
case Dia is
when Segunda => Levantar_mal_disposto;
Inicio_Trabalho;
when Terça .. Quinta => Continuar_Trabalho;
when Sexta => Fim_Trabalho;
when others => Farra
end case;
- Nota: Tem que se prever todos os valores possíveis da variável. Ou então usar a alternativa others. Se não dá erro de compilação.
Introdução à programação em Ada 2005 Pág. 12
Luís Miguel Pinho – Instituto Superior de Engenharia do Porto Outubro de 2006
6. Ciclos
- Há três tipos de ciclos
ciclo ::= [identificador :]
[esquema- de-iteração] loop
instruções;
end loop [identificador];
esquema- de-iteração ::=
for índice in [reverse] intervalo-discreto
|while expressão- booleana
- Exemplos
loop - - ciclo infinito
Adquire_valor_sensor;
Calcula_Controlo:
Actua;
end loop;
V: array(1 .. 10) of Integer;
-- ...
for I in 1 .. 10 loop
V(I) := Adquire_valor();
end loop;
V: array(1 .. 10) of Integer;
I : Integer := 1;
-- ...
while I <= 10 loop
Adquire_valor(V(I));
I := I + 1;
end loop;
- Notas:
- A variável I no ciclo for apenas existe dentro do ciclo for. E não é declarada.
- O atributo ‘Range (que já foi apresentado) pode ser utilizado num ciclo for para fornecer a gama de valores de um vector
• for I in V’Range loop
• Isso quer dizer que o mesmo ciclo pode ser utilizado para vectores de tamanhos diferentes, sem ser necessário guardarmos o tamanho do vector
Introdução à programação em Ada 2005 Pág. 13
Luís Miguel Pinho – Instituto Superior de Engenharia do Porto Outubro de 2006
- Pode-se ter condições dentro do ciclo para sair
V: array(1 .. 10) of Integer;
-- ...
for I in 1 .. 10 loop
Valor:=Adquire_valor();
exit when Valor < 0;
V(I):=Valor;
end loop;
loop - - ciclo infinito
Adquire_valor_sensor;
Calcula_Controlo:
exit when controlo_incorrecto;
Actua;
end loop;
- O exit força a saída do ciclo para a primeira instrução seguinte
- Se tivermos ciclos encadeados
- O exit faz sair do ciclo mais próximo
- Ou então pode ser utilizado para indicar de qual ciclo queremos sair
• podemos dar nomes aos ciclos
V: array(1 .. 10) of Integer;
-- ...
ciclo_exterior:
loop - - ciclo infinito
for I in 1 .. 10 loop
Valor:=Adquire_valor();
exit ciclo_exterior when Valor < 0;
V(I):=Valor;
end loop;
Calcula_Controlo:
Actua;
end loop;
- Não existe continue em Ada
- Não há forma de continuar um ciclo saltando certas instruções
- Mas pode usar-se um if
- Existe goto, mas se quiserem passar à disciplina ...
Introdução à programação em Ada 2005 Pág. 14
Luís Miguel Pinho – Instituto Superior de Engenharia do Porto Outubro de 2006
7. Subprogramas
- Existem dois tipos de subprogramas
- Procedimento (abstracção de uma acção)
- Função (abstracção de um valor)
- Ambos podem ter parâmetros
- Apenas as funções retornam valor
- E têm que retornar
- Um subprograma tem duas partes
- A especificação (define a interface - nome e parâmetros)
- O corpo (define a acção ou o algoritmo que é executado quando se invoca o subprograma)
- Se não for precisa a especificação pode ser omitida
- Neste caso o próprio corpo serve de especificação
declaração-de-subprograma ::=
especificação- de- subprograma;
especificação-de-subprograma ::=
procedure nome [parâmetros]
| function nome [parâmetros] return tipo_retorno
parâmetros::= (definição{; definição})
definição::= lista : modo tipo [:= valor_por_defeito]
lista ::= nome{, nome}
modo ::= [in] | out | in out
valor-por-defeito ::= expressão
- Exemplos de especificação
procedure Reset; -- Sem parâmetros
procedure Incrementa( Value : in out Integer;
Step : in Integer := 1);
function Minimo(X, Y : Integer) return Integer;
- Existem três formas de passar parâmetros
- in O parâmetro não é modificado dentro do subprograma
- (pode ter um valor por defeito)
- out O subprograma tem que atribui um valor ao parâmetro
- in out O subprograma pode modificar o parâmetro
Introdução à programação em Ada 2005 Pág. 15
Luís Miguel Pinho – Instituto Superior de Engenharia do Porto Outubro de 2006
- As funções só podem ter parâmetros do tipo in
- Por defeito os parâmetros são do tipo in
- As formas de passar parâmetros não têm nada que ver com o método de passagem de parâmetros
- Parâmetros in podem ser passados por referência
- O compilador garante que não há alterações
- Parâmetros in out podem ser passados por cópia
- O compilador faz a cópia no início e no fim
- Temos que tomar algum cuidado com os parâmetros
- Se o parâmetro for do tipo out ou in out temos que passar uma variável para o subprograma (não pode ser um valor fixo)
- Se o parâmetro for do tipo in não o podemos modificar no subprograma
- Podem existir subprogramas com o mesmo nome
- Mas têm que se destinguir pelos parâmetros
- Ou, nas funções, também pelo tipo de retorno
- Corpo de subprogramas
corpo-de-subprograma ::=
especificação-de-subprograma is
{declaração}
begin
instruções;
end nome;
- O corpo tem uma parte inicial declarativa, onde se podem declarar variáveis locais ao subprograma
- Ou outros subprogramas, porque ao contrário do C/C++ (mas tal como o Pascal) em Ada pode-se declarar subprogramas dentro de subprogramas
- Uma função tem que ter pelo menos um return, e todos os caminhos possíveis dentro da função têm que atingir um return
Introdução à programação em Ada 2005 Pág. 16
Luís Miguel Pinho – Instituto Superior de Engenharia do Porto Outubro de 2006
- Exemplos de corpos de subprogramas
type int_array is array(1..100) of Integer;
-- …
procedure Minimo_vector( vec: in int_array; Min: out Integer) is
function Minimo(X, Y : Integer) return Integer is
begin
if X < Y then
return X;
else
return Y;
end Minimo;
m: Integer := vec(vec’First);
begin
for I in vec’First +1 .. vec’Last loop
m := Minimo(vec(I) , m );
end loop;
end Minimo_vector;
- Invocação de subprogramas
- É uma simples expressão:
procedure Reset; -- Sem parâmetros
procedure Incrementa( Value : in out Integer;
Step : in Integer := 1);
function Minimo(X, Y : Integer) return Integer;
-- …
X : Integer := 1;
begin
Incrementa(X,2); --> associação posicional
Incrementa( Step => 2, Value => X); --> associação por nome
-- parâmetros podem ter qualquer ordem
Incrementa(X); -- > parâmetros por defeito
Reset; -- > se não tiver parâmetros
-- não é necessário colocar parênteses
Incrementa(X, Minimo(2,3) ); -- >funções podem ser usadas
-- em expressões (procedimentos não)
end;
Introdução à programação em Ada 2005 Pág. 17
Luís Miguel Pinho – Instituto Superior de Engenharia do Porto Outubro de 2006
8. Excepções
- A linguagem Ada providencia mecanismos para processar erros em tempo de execução
- A acção por defeito quando uma excepção é levantada é terminar o programa (ou terminar a tarefa, se a excepção não for na tarefa principal)
- Se não queremos que termine temos que ter um processador de excepções (exception handler)
- Especifica quais as excepções a processar, e o que fazer quando ocorrem
- As excepções não devem ser utilizadas para situações normais e previstas, porque tornam o programa mais lento e imprevisível
- O sítio onde a excepção ocorre não pode ser facilmente determinado, o que pode obrigar a código muito complexo
- É possível desactivar as verificações em tempo de execução (utilizando a pragma Supress), o que deve apenas ser feito depois do programa estar completamente verificado (isto é possível?)
- Excepções predefinidas
- Constraint_Error
- Quando se tenta atribuir um valor for a do intervalo declarado
- Quando o índice de um array está fora dos limites
- Quando se usa um apontador nulo
- Quando se produz um erro numérico (por exemplo divisão por zero)
- Storage_Error
- Quando se tenta reservar memória dinâmica e não existe disponível
- Tasking_Error
- Quando uma tarefa tenta fazer rendezvous com outra que já terminou
- Quando existe uma excepção na elaboração de uma tarefa, a tarefa que criou essa tarefa recebe a excepção Tasking_Error
- Program_Error
- Quando existe um select em que todas as opções estão fechadas (as guardas dão falso)
- Quando uma tarefa fica bloqueada durante a execução de um subprograma de um objecto protegido
- Quando um objecto protegido é destruído, mas ainda existem tarefas nas filas de espera desse objecto, essas tarefas recebem a excepção
- Quando a avaliação de uma barreira numa entry de um objecto protegido resulta numa excepção, todas as tarefas bloqueadas no objecto recebem Program_Error
Introdução à programação em Ada 2005 Pág. 18
Luís Miguel Pinho – Instituto Superior de Engenharia do Porto Outubro de 2006
- Processamento de excepções
- Define-se um “exception handler” no bloco do qual queremos processar as excepções
- Um bloco pode ser:
- Um subprograma
- Uma tarefa
- Um ciclo/if/etc…
- Blocos declarados no código
- when others é usado para apanhar todas as outras excepções
- Se o bloco onde ocorre a excepção não a processar esta é enviada ao bloco mais englobante
- E assim sucessivamente (o limite é a tarefa)
- Podemos dar um nome à ocorrência da excepção, para saber mais sobre ela
- A package Ada.Exceptions tem vários subprogramas para obter informação sobre excepções
begin -- incio do bloco -- …. exception -- exception handler when Contraint_Error => Processa_Excepcao; when Program_Error => Outro_Processamento; when Nome: others => Put(“Excepção sem nome:”); Put(Ada.Exceptions.Exception_Information(Nome)); end Teste; -- fim do bloco
Introdução à programação em Ada 2005 Pág. 19
Luís Miguel Pinho – Instituto Superior de Engenharia do Porto Outubro de 2006
9. Estrutura de programas
- Os subprogramas são unidades de programa
- Existem outras: packages, tarefas e objectos protegidos
- Um package, é um módulo que contém declaração de tipos, variáveis, subprogramas e outros packages
- Os subprogramas também são unidades de compilação
- packages também são
- Um ficheiro fonte pode conter mais do que uma unidade de compilação
- O GNAT só permite uma unidade de compilação por ficheiro
- Os subprogramas e packages já compilados formam uma biblioteca de compilação
- Um programa executável forma-se a partir de uma biblioteca que inclua um procedimento principal
- O nome do procedimento não é fixo (no caso do GNAT é o nome do ficheiro fonte)
- Um programa Ada compõe-se de
- Um procedimento principal
- Outros subprogramas e packages escritas pelo utilizador
- Subprogramas e packages predefinidos (possivelmente já compilados)
- Quando se pretende utilizar um package é necessário utilizar cláusulas de contexto logo no início do ficheiro fonte
- Cláusula with (with nome_da_package;)
- Serve para assinalar que pretendemos utilizar aquela package
- Cláusula use (use nome_da_package;)
- Serve para assinalar que não queremos referenciar o caminho todo até aos elementos da package
- Como já referido packages podem conter outros packages
- Aos últimos chama-se filhos dos primeiros
- O nome do package é constituído pelo nome dos seus ascendentes separados por ponto
- Exemplo:
- Existe uma package Ada
- Tem uma package filha chamada Text_IO que contém os subprogramas de interface com a consola (para texto)
- Assim para referenciar a package Texto_IO da package Ada usa-se:
Ada.Text_IO
Introdução à programação em Ada 2005 Pág. 20
Luís Miguel Pinho – Instituto Superior de Engenharia do Porto Outubro de 2006
-- O seguinte programa utiliza o procedimento Put da package Ada.Text_IO
-- para escrever uma String (“Hello World”) no monitor
with Ada.Text_IO;
use Ada.Text_IO;
procedure Hello_World is
begin
Put(“Hello World”);
end Hello_World;
-- Se não quisermos referenciar directamente o procedimento Put, podemos
-- omitir a cláusula use (agora temos que usar o caminho todo para Put)
with Ada.Text_IO;
procedure Hello_World is
begin
Ada.Text_IO.Put(“Hello World”);
end Hello_World;
- Ok, mas e agora? Como executar?
- A resposta depende um bocado de cada compilador
- como em qualquer linguagem
- No caso do GNAT a resposta é simples:
- O ficheiro fonte tem que ter a extensão .adb
- O ficheiro fonte só pode ter um procedimento (pode ter vários, desde que os outros estejam dentro do primeiro)
- O nome do procedimento tem que ser o nome do ficheiro
- Estas regras não são completamente obrigatórias, mas para já servem :)
-
- Portanto para executar o programa anterior (Hello World) utilizando o GNAT:
- Escrever aquele código num ficheiro de texto chamado hello_world.adb
- Executar o compilador: gnatmake hello_world
- Correr o programa: ./hello_world
Introdução à programação em Ada 2005 Pág. 21
Luís Miguel Pinho – Instituto Superior de Engenharia do Porto Outubro de 2006
- Não é preciso passar ao compilador a extensão .adb (mas tem que existir)
- O compilador cria um executável com o nome do ficheiro fonte (sem o .adb)
- Para apenas compilar : gnatmake -c hello_world
- O compilador tem três fases:
• A fase de compilação propriamente dita (gnat1)
o Cria dois ficheiros: um .o (código objecto) e um .ali que contém informação que vai ser utilizada nas fases seguintes (conteúdo dos ficheiros fontes, relação entre ficheiros, timestamp, etc…)
• A fase de binding (gnatbind)
o Serve para verificar as relações entre ficheiros de compilação
• A fase de linkagem (gnatlink)
o Serve para criar o executável
Introdução à programação em Ada 2005 Pág. 22
Luís Miguel Pinho – Instituto Superior de Engenharia do Porto Outubro de 2006
10. Entrada e Saída
- Como já referido existe um package que contém subprogramas para entrada/saída de texto (Ada.Text_IO)
- Put(Item: in String);
- Put_Line(Item: in String);
- Get(Item: out String);
- Get_Line(Item: out String; Last: out Integer);
- New_Line;
- Existem outras duas packages para Integer e Float
- Ada.Integer_Text_IO
- Put(Item: in Integer);
- Get(Item: out Integer);
- Ada.Float_Text_IO;
- Put(Item: in Float);
- Get(Item: out Float);
- Parece muita coisa (e é porque temos que referenciar cada uma em separado), mas o objectivo da linguagem Ada não é o de poupar na escrita de código :) mas sim poupar na manutenção (o mais caro)
with Ada.TexT_IO; use Ada.Text_IO;
with Ada.Integer_Text_IO; use Ada.Integer_Text_IO;
procedure Teste is
I: Integer;
begin
Put(“Introduza um número: ”); -- package Ada.Text_IO;
Get(I); -- package Ada.Integer_Text_IO;;
Put(“O número introduzido foi “); -- package Ada.Text_IO;
Put(I); -- package Ada.Integer_Text_IO;;
New_Line; -- package Ada.Text_IO;
end Teste;
Introdução à programação em Ada 2005 Pág. 23
Luís Miguel Pinho – Instituto Superior de Engenharia do Porto Outubro de 2006
- Existe um problema quando se quer ler Strings do teclado
- Quando se cria uma String é necessário especificar qual o tamanho da String
- Quando se lê uma String (tem um tamanho) com o Get somos obrigados a ler tantos caracteres como o tamanho da String
- Para resolver isto é necessário utilizar Get_Line, não Get
- Get_Line devolve também qual o tamanho da String lida (o segundo parâmetro). A partir desse momento utilizamos sempre esse tamanho
-- O seguinte programa utiliza o procedimento Get_Line da package
-- Ada.Text_IO para ler uma String (do teclado) e depois utiliza
-- Put, para a colocar no monitor
with Ada.Text_IO;
use Ada.Text_IO;
procedure Hello_Utilizador is
S: String(1..80);
Fim: Integer;
begin
Put(“Introduza o seu nome (< 80 caracteres): “);
Get_Line( S , Fim );
Put(“Hello “);
Put_Line( S( 1 .. Fim ) );
end Hello_Utilizador;
- Para utilizarmos Strings sem tamanho predefinido existe um tipo de dados Unbounded_String
- Os arrays podem não ter limites
- Se por acaso o utilizados entrar mais de 80 caracteres os restantes caracteres ficam no buffer do teclado, o que pode originar erro nas leituras seguintes do teclado
- Mas não na leitura actual. O Get_Line nunca tenta colocar na String mais caracteres do que o tamanho desta
- Existe um problema quando se lê uma String do teclado após se ter lido um número
- O problema não tem a ver com a linguagem, nem com o compilador (é o célebre problema do getch())
- Para resolver isso, sempre que vamos ler uma string, o melhor é utilizaro o procedimento Skip_Line da package Ada.Text_IO
Introdução à programação em Ada 2005 Pág. 24
Luís Miguel Pinho – Instituto Superior de Engenharia do Porto Outubro de 2006
-- O seguinte programa é semelhante ao anterior, mas antes de ler o nome,
-- lê a idade. Logo, é necessário colocar o procedimento Skip_Line
with Ada.Text_IO;
use Ada.Text_IO;
procedure Hello_Utilizador is
S: String(1..80);
Fim: Integer;
Idade: Integer;
begin
Put(“Introduza a sua idade: “);
Get(Idade);
Skip_Line;
Put(“Introduza o seu nome (< 80 caracteres): “);
Get_Line( S , Fim );
Put(“Hello “);
Put_Line( S( 1 .. Fim ) );
Put(“A sua idade é “);
Put(Idade);
Put(“ anos”);
end Hello_Utilizador;
Introdução à programação em Ada 2005 Pág. 25
Luís Miguel Pinho – Instituto Superior de Engenharia do Porto Outubro de 2006
11. Modelo de Concorrência
- Ada permite a especificação de tarefas / tipo de tarefas, as quais iniciam execução sem necessidade de activação explícita.
- Para comunicação / sincronização entre tarefas temos disponíveis vários mecanismos:
- Rendezvous (Comunicação síncrona)
- Objectos protegidos (Recursos partilhados - mecanismo de alto nível)
- Objectos de sincronização (mecanismo de baixo nível)
- Existe a possibilidade de definição de alternativas de comunicação/sincronização (select)
- No rendezvous
- No acesso a objectos protegidos
- Relógio
- No Ada, além de um relógio normal (Calendar) existe um relógio de tempo-real, com precisão mínima de 1µS
- Existe um mecanismo de suspensão de uma tarefa por um tempo determinado
- Atraso relativo (delay)
- Atraso absoluto (delay until)
- Prioridades
- Em Ada podemos especificar prioridades para tarefas, e para o tecto de prioridades de objectos protegidos
- As prioridades podem ser dinâmicas
- Despacho das tarefas
- Podemos especificar a forma pretendida para o despacho das tarefas.
- O anexo de sistemas de tempo-real especifica que tem que existir pelo menos FIFO_Within_Priorities (despacho por prioridades, com FIFO na mesma prioridade
pragma Task_Dispatching_Policy(FIFO_Within_Priorities);
- Interacção com recursos
- Podemos especificar como se comporta a interacção entre as tarefas e os recursos partilhados.
- O anexo de sistemas de tempo-real especifica que tem que existir pelo menos Ceiling_Locking (implementa o protocolo de Immediate Ceiling Protocol para resolver a inversão de prioridades)
pragma Locking_Policy(Ceiling_Locking);
Introdução à programação em Ada 2005 Pág. 26
Luís Miguel Pinho – Instituto Superior de Engenharia do Porto Outubro de 2006
- Filas de espera no acesso a recursos
- O anexo de sistemas de tempo-real especifica que têm que existir duas formas possíveis de espera no acesso a recursos: FIFO_Queuing e Priority_Queuing.
pragma Queuing_Policy(Priority_Queuing);
- Quando se pretende um programa que implemente o modelo de escalonamento por prioridades, que resolva o problema da inversão de prioridades é necessário especificar
- FIFO_Within_Priorities para o tipo de despacho, Ceiling_Locking para o acesso a recursos partilhados e Priority_Queuing para acesso a filas de espera
- A linguagem permite a especificação de outros modelos, para a implementação de modelos de escalonamento diferentes (e.g. EDF, Round Robin e escalonamento hierárquico)
- Implementação da Concorrência
- A questão é: Como é que o Ada implementa a concorrência
- A resposta é: depende :)
- O compilador pode mapear a concorrência nos serviços disponibilizados pelo Sistema Operativo (por exemplo GNAT para Windows/Linux)
- Quer dizer que o modelo de concorrência só pode ser cumprido se o SO for de tempo-real (por exemplo GNAT para VxWorks/RTEMS)
- É fácil de implementar se o SO for de tempo-real e suporte interface POSIX
- O compilador pode implementar o seu próprio runtime (por exemplo DCCI Tartan Ada Compilar ou GNAT NRT)
- Directamente em cima do hardware
- Geralmente é para arquitecturas específicas
- Ou uma mistura dos dois
- O compilador disponibiliza uma camada entre o programa e o sistema operativo para implementar mecanismos que o SO não suporte (por exemplo GNAT para DOS, ou GNAT + Florist para Linux)
- Um exemplo interessante é o A#, que compila Ada para a plataforma .Net
http://www.usafa.af.mil/df/dfcs/bios/mcc_html/a_sharp.cfm
Introdução à programação em Ada 2005 Pág. 27
Luís Miguel Pinho – Instituto Superior de Engenharia do Porto Outubro de 2006
12. Tarefas
- São a unidade de concorrência
- Declaram-se como variáveis ou tipos de dados na zona de declaração dos blocos.
- Podemos especificar prioridades para tarefas (podem ser dinâmicas)
- As prioridades definem-se através de pragmas
- Podemos criar tarefas dentro de tarefas (hierarquia)
Declaração ::= task [type] nome [Discriminantes] [is {task_item} [private {task_item}] end [nome]];
Discriminantes::=
(Nome: Tipo [{;Nome: Tipo}]) task_item::=
entry|pragma Corpo::=
task body nome is [{declarações}] begin {instruções} end [nome];
Introdução à programação em Ada 2005 Pág. 28
Luís Miguel Pinho – Instituto Superior de Engenharia do Porto Outubro de 2006
with Ada.Text_IO; procedure Uma_Tarefa is -- Declaração de uma tarefa task tarefa ; -- Corpo da tarefa task body tarefa is begin for Count in 1..5 loop Ada.Text_IO.Put_Line(Item => "Tarefa "); end loop; end tarefa; begin -- Inicio da tarefa principal -- A outra tarefa é activada ao mesmo tempo que o corpo -- do bloco em que foi declarada for Count in 1..5 loop Ada.Text_IO.Put(Item => "Tarefa principal"); Ada.Text_IO.New_Line; end loop; end Uma_Tarefa;
Introdução à programação em Ada 2005 Pág. 29
Luís Miguel Pinho – Instituto Superior de Engenharia do Porto Outubro de 2006
with Ada.Text_IO; procedure Tarefas is -- Declaração de um tipo de tarefas task type tarefa (Msg: Character); -- Podemos utilizar discriminates nas tarefas, para poder
identificar cada uma -- das tarefas -- Corpo das tarefas deste tipo task body tarefa is begin for Count in 1..5 loop Ada.Text_IO.Put_Line(Item => "Tarefa " & Msg); end loop; end tarefa; Task_A: tarefa(Msg => 'A'); Task_B: tarefa(Msg => 'B'); begin -- Inicio da tarefa principal -- As outras tarefas são activadas ao mesmo tempo que o corpo -- do bloco em que foram declaradas for Count in 1..5 loop Ada.Text_IO.Put(Item => "Tarefa principal"); Ada.Text_IO.New_Line; end loop; end Tarefas;
Introdução à programação em Ada 2005 Pág. 30
Luís Miguel Pinho – Instituto Superior de Engenharia do Porto Outubro de 2006
pragma Task_Dispatching_Policy(FIFO_Within_Priorities); -- serve para referir que este programa faz o despacho de tarefas -- por prioridades e FIFO dentro da mesma prioridade. -- É uma pragma de configuração, porque aplica-se -- ao programa todo. Por isso é colocada no início with System; -- Aqui está declarado o tipo Priority with Ada.Text_Io; procedure Tarefas_Prioridades is pragma Priority(System.Priority'First); -- serve para referir que a tarefa principal tem prioridade -- igual à mais baixa -- É o único sítio onde se pode utilizar esta pragma na -- declaração de um subprograma -- Declaração de um tipo de tarefas task type tarefa (Msg: Character; Prio: System.Priority) is pragma Priority(Prio); -- serve para referir que este tipo de tarefa tem -- prioridade igual a Prio. Como Prio é um discriminante -- que pode ser diferente para cada tarefa, a prioridade -- pode ser diferente para cada tarefa end tarefa; -- Corpo das tarefas deste tipo task body tarefa is begin for Count in 1..5 loop Ada.Text_Io.Put_Line(Item => "Tarefa " & Msg); end loop; end tarefa; Task_A: tarefa(Msg => 'A', Prio => System.Priority'First+1); Task_B: tarefa(Msg => 'B', Prio => System.Priority'First+2); begin -- Inicio da tarefa principal null; end Tarefas_Prioridades;
Introdução à programação em Ada 2005 Pág. 31
Luís Miguel Pinho – Instituto Superior de Engenharia do Porto Outubro de 2006
13. Rendezvous
- Tarefas podem comunicar de forma síncrona entre elas
- Uma é o cliente e outra o servidor
- O rendezvous pode (ou não) servir para trocar informação
- A tarefa servidora declara na sua interface quais os serviços que disponibiliza (entries)
- O cliente tem que saber o nome do servidor para poder ligar
- Como a ligação é síncrona o cliente fica bloqueado enquanto não acaba o serviço no servidor
- Como a ligação é síncrona o cliente fica bloqueado enquanto não acaba o serviço no servidor
- Rendezvous pode ser usado para troca de dados, ou para que o servidor efectue uma acção em benefício do cliente
- Esta forma de interacção é parecida com o RPC
task servidor is entry serviço; end servidor; task body servidor is begin -- ... accept serviço; -- ... end servidor;
Introdução à programação em Ada 2005 Pág. 32
Luís Miguel Pinho – Instituto Superior de Engenharia do Porto Outubro de 2006
with Ada.Text_IO; use Ada.Text_IO; procedure Tarefas_Rendezvous is -- tarefa servidora task servidor is entry start; -- Declaração do ponto de ligação end servidor; -- Corpo da tarefa servidora task body servidor is begin accept start; -- Aqui o servidor fica bloqueado à espera for Count in 1..5 loop Put_Line(Item => "Servidor"); end loop; end servidor; -- tarefa cliente task cliente; -- Corpo da tarefa cliente task body cliente is begin Put_Line("Pressione Enter para iniciar o servidor"); Skip_Line; servidor.start; -- Aqui o cliente fica bloqueado à espera -- se o servidor não estiver já à espera -- na entry end cliente; begin -- Inicio da tarefa principal null; end Tarefas_Rendezvous;
Introdução à programação em Ada 2005 Pág. 33
Luís Miguel Pinho – Instituto Superior de Engenharia do Porto Outubro de 2006
task servidor is entry servico1(Dados: in Tipo; Result: out Tipo); entry servico2(Dados: in Tipo); end servidor; task body servidor is begin -- ... accept servico1(Dados:in Tipo; Result: out Tipo) do -- … Result:= Qualquer_coisa; end servico1; -- … accept servico2(Dados: in tipo) do -- … end servico2; -- ... end servidor;
Introdução à programação em Ada 2005 Pág. 34
Luís Miguel Pinho – Instituto Superior de Engenharia do Porto Outubro de 2006
with Ada.Text_IO; use Ada.Text_IO; with Ada.Integer_Text_IO; use Ada.Integer_Text_IO; procedure Tarefas_Rendezvous2 is -- tarefa servidora task Servidor is entry Start; -- Declaração do ponto de ligação entry Serviço1(Result: out Integer); entry Serviço2(dados: Integer); end Servidor; -- Corpo da tarefa servidora task body Servidor is Valor: Integer := 0; begin accept Start; -- Aqui o servidor fica bloqueado à espera for Count in 1..5 loop accept Serviço2(dados: Integer) do Put(Item => "Servidor recebeu "); Put(dados); New_Line; Valor:= Valor + dados; end Serviço2; end loop; accept Serviço1(Result: out Integer) do Result:= Valor; end Serviço1; end Servidor; -- tarefa cliente task Cliente; -- Corpo da tarefa cliente task body Cliente is Val: Integer; begin Put_Line("Pressione Enter para iniciar o servidor"); Skip_Line; Servidor.Start; -- Aqui o servidor fica bloqueado à espera for Count in 1..5 loop Put_Line("Entre valor inteiro para enviar ao servidor: "); Get(Val); Servidor.Serviço2(Val); end loop; Servidor.Serviço1(Val); Put("O servidor enviou-me a soma dos valores entrados: "); Put(Val); New_Line; end Cliente; begin -- Inicio da tarefa principal null; end Tarefas_Rendezvous2;
Introdução à programação em Ada 2005 Pág. 35
Luís Miguel Pinho – Instituto Superior de Engenharia do Porto Outubro de 2006
14. Relógios e Temporizadores
- Existem dois tipos de relógios
- Um relógio normal (Ada.Calendar.Clock), como se fosse um relógio de parede
- Um relógio de tempo real (Ada.Real_Time.Clock)
- Geralmente são o mesmo relógio de hardware, mas são utilizados de forma diferente
- Ada.Calendar
- O tipo Time pode representar qualquer coisa (geralmente representa segundos desde as 0 horas do dia 1/1/70, como em Unix, mas não se pode garantir)
- A função Clock retorna o Time actual
- O tipo Duration representa uma diferença de instantes. Não pertence à package Ada.Calendar, mas existe globalmente (package Standard)
- Existem funções para retirar Ano/Mês/Dia a partir do Time
- Ada.Real_Time
- O tipo Time pode representar qualquer coisa (geralmente é o mesmo de Calendar, mas não se pode garantir)
- A função Clock retorna o Time actual
- O tipo Time_Span representa uma diferença de instantes
- Existem funções para converter ms/µs/ns em Time_Span
- É preciso ter cuidado para não misturar estes dois relógios
- Existem dois tipos de temporizadores
- Temporizadores de tempo de execução (Ada.Execution_Time)
- Permitem contabilizar o tempo de execução de uma tarefa
- Alarme no caso de “overrun”
- Disponíveis para uma tarefa ou grupo de tarefas (Ada.Execution_Time.Timers e Ada.Execution_Time.Group_Budgets)
- Alarmes de tempo real (Ada.Real_Time.Timing_Events)
- Permite “disparar” eventos em tempos específicos
- Não utiliza tarefas
- Tempo é dado pelo Time de Ada.Real_Time
Introdução à programação em Ada 2005 Pág. 36
Luís Miguel Pinho – Instituto Superior de Engenharia do Porto Outubro de 2006
15. Atrasos
- Existem dois tipos de atrasos
- Absoluto (delay until)
- Serve para indicar que a tarefa deve ficar suspensa até um determinado instante
- A tarefa pode ser libertada apenas depois desse tempo, depende do escalonamento
- Usa-se:
delay until Tempo;
Tempo tem que ser do tipo Time (pode ser Calendar Time, ou Real_Time Time)
- Relativo (delay)
- Serve para indicar que a tarefa deve ficar suspensa durante um determinado instante
- A tarefa pode ficar bloqueada mais do que esse tempo, depende do escalonamento
- Usa-se:
delay Intervalo;
Intervalo tem que ser do tipo Duration (não pode ser Real_Time)
- Quando se quer usar delay com Real_Time.Time_Span existe uma função que converte Time_Span em Duration
- Embora o atraso relativo (delay) possa ser usado, também pode dar problemas
- O problema é que a instrução “delay (Start + 10.0) – Clock” não é indivisível. A tarefa pode ser interrompida após ter calculado um intervalo de 8 segundos, e quando executa outra vez já podem ter passado vários segundos, mas o intervalo será na mesma de 8 segundos
Start:= Clock; Faz_Acção; delay (Start + 10.0) - Clock;
Introdução à programação em Ada 2005 Pág. 37
Luís Miguel Pinho – Instituto Superior de Engenharia do Porto Outubro de 2006
-- Este programa atrasa a execução durante três segundos -- Utilizando o tipo Duration with Ada.Text_IO; use Ada.Text_IO; procedure Relogio is Interval: Duration:= 3.0; -- Como Duration baseia-se em
-- vírgula flutuante -- não pode ser := 3,
-- tem que ser := 3.0 begin Put_Line("Começou o programa"); delay Interval; Put_Line("Supostamente passaram 3 segundos"); end Relogio; -- Este programa atrasa a execução durante três segundos -- Utilizando o tipo Ada.Real_Time.Time_Span with Ada.Text_IO; use Ada.Text_IO; with Ada.Real_Time; use Ada.Real_Time; procedure Relogio1 is Interval: Time_Span := Milliseconds(3000); -- temos que usar as -- funções de conversão begin Put_Line("Começou o programa"); delay To_Duration(Interval); Put_Line("Supostamente passaram 3 segundos"); end Relogio1;
Introdução à programação em Ada 2005 Pág. 38
Luís Miguel Pinho – Instituto Superior de Engenharia do Porto Outubro de 2006
16. Synchronous/Asynchronous Task Control
- Synchronous Task Control
- Um semáforo básico, que pode ser usado para suspensão ou para implementar mecanismos mais complexos.
- Especificação (simplificada):
package Ada.Synchronous_Task_Control is type Suspension_Object is private; procedure Set_True(S : in out Suspension_Object); procedure Set_False(S : in out Suspension_Object); function Current_State(S : Suspension_Object) return Boolean; procedure Suspend_Until_True(S : in out Suspension_Object); private ... -- a implementação depende do compilador end Ada.Synchronous_Task_Control;
- Um objecto tem dois estados: verdadeiro e falso. Inicialmente está a falso.
- O procedimento Suspend_Until_True bloqueia a tarefa no objecto até outra tarefa executar Set_True.
- Apenas uma tarefa pode estar suspensa num objecto (dá excepção se uma segunda tentar)
- Asynchronous Task Control
- No mecanismo anterior, apenas a própria tarefa se pode suspende.
- O mecanismo assíncrono permite que uma tarefa seja suspensa por outra:
with Ada.Task_Identification; package Ada.Asynchronous_Task_Control is pragma Preelaborate(Asynchronous_Task_Control); procedure Hold(T : in Ada.Task_Identification.Task_Id); procedure Continue(T : in Ada.Task_Identification.Task_Id); function Is_Held(T : Ada.Task_Identification.Task_Id) return Boolean; end Ada.Asynchronous_Task_Control;
Introdução à programação em Ada 2005 Pág. 39
Luís Miguel Pinho – Instituto Superior de Engenharia do Porto Outubro de 2006
17. Interfaces
- Uma novidade do Ada 2005 foi a introdução de Interfaces (como Java).
- Como não existe integração de OO com concorrência (não se pode herdar de/para tarefas), as Interfaces podem ser usadas para permitir uma integração limitada
- São permitidos 2 tipos de interfaces para serem utilizados com concorrência:
- Synchronised:Pode ser implementada por tarefas e objectos protegidos
- Task: Pode ser implementada apenas por tarefas
- Protected: Pode ser implementada apenas por objectos protegidos
-- A interface TI package Pkg is
type TI is task interface; procedure P(X: in TI) is abstract; procedure Q(X: in TI; I: in Integer) is null;
end Pkg;
-- pode ser implementada por: package PT1 is
task type TT1 is new TI with entry P; -- P e Q são entries entry Q(I: in Integer);
end TT1; end PT1; -- ou por package PT2 is
task type TT2 is new TI with entry P; -- P é entry
end TT2; -- Q é uma procedure procedure Q(X: in TT2; I: in Integer);
end PT2;
Introdução à programação em Ada 2005 Pág. 40
Luís Miguel Pinho – Instituto Superior de Engenharia do Porto Outubro de 2006
18. O Perfil Ravenscar
- Os mecanismos de Concorrência do Ada são muito complexos
- Em 1997 chegou-se à conclusão que era necessário restringir a sua utilização para:
- Aumentar a eficiência dos executivos de tempo-real, removendo mecanismos com grandes overheads
- Reduzir o não determinismo para aplicações críticas
- Simplificar os executivos de tempo-real, para aplicações de alta integridade
- Remover mecanismos que não podem ser formalizados
- Remover mecanismos que impedem a análise de resposta temporal das aplicações
- Foi então criado o perfil Ravenscar (Reliable Ada Verifiable Executive Needed for Scheduling Critical Applications in Real-time!)
- Ravenscar é uma pequena terra no norte de Inglaterra, onde decorreu a reunião
- O perfil tem muitas restrições
- No entanto, tem o suficiente para implementar aplicações de tempo-real, segundo o modelo de escalonamento preemptivo por prioridades fixas
- Este perfil foi introduzido na Norma em 2005
- Pragma de configuração
pragma Profile(Ravenscar);
Introdução à programação em Ada 2005 Pág. 41
Luís Miguel Pinho – Instituto Superior de Engenharia do Porto Outubro de 2006
- A pragma Ravenscar é equivalente a:
pragma Task_Dispatching_Policy(FIFO_Within_Priorities);
pragma Locking_Policy(Ceiling_Locking);
pragma Detect_Blocking;
pragma Restrictions(
No_Abort_Statements, No_Dynamic_Attachment, No_Dynamic_Priorities, No_Implicit_Heap_Allocations, No_Local_Protected_Objects, No_Local_Timing_Events, No_Protected_Type_Allocators, No_Relative_Delay, No_Requeue_Statements, No_Select_Statements, No_Specific_Termination_Handlers, No_Task_Allocators, No_Task_Hierarchy, No_Task_Termination, Simple_Barriers, Max_Entry_Queue_Length => 1, Max_Protected_Entries => 1, Max_Task_Entries => 0, No_Dependence => Ada.Asynchronous_Task_Control, No_Dependence => Ada.Calendar, No_Dependence => Ada.Execution_Time.Group_Budget, No_Dependence => Ada.Execution_Time.Timers, No_Dependence => Ada.Task_Attributes);
- Restrições
- Tarefas e objectos protegidos apenas ao nível das bibliotecas (nada de hierarquias)
- Não é permitido:
- reservar/libertar dinamicamente tarefas/objectos protegidos
- requeue, ATC, Abort
- entries nas tarefas
- Prioridades dinâmicas
- Ada.Calendar, Delays relativos
- entries nos objectos protegidos, em que a barreira não é uma variável booleana declarada dentro do próprio objecto
- Uma tarefa tentar executar uma entry de um objecto protegido, em que já lá está outra tarefa
- Asynchronous Task Control
- Todas as formas do select
- Atributos de tarefas definidos pelo utilizador
Introdução à programação em Ada 2005 Pág. 42
Luís Miguel Pinho – Instituto Superior de Engenharia do Porto Outubro de 2006
- Ficou ainda
- Tarefas e objectos protegidos (com as restrições)
- pragmas Atomic e Volatile
- delay until
- Ceiling_Locking e FIFO_Within_Priorities
- Atributo Count (mas não nas barreiras)
- Identificadores das tarefas
- Synchronous Task Control
- Descriminantes nas tarefas
- package Real_Time
- Protected procedures como processamento de interrupções
- O modelo de escalonamento preemptivo por prioridades fixas é:
- Um número fixo de actividades (tarefas)
- Não há criação/destruição de tarefas
- Cada tarefa é libertada apenas por um evento, mas que pode acontecer um número ilimitado de vezes
- Este evento pode ser temporal (para uma tarefa periódica) ou esporádico (de uma outra tarefa ou do ambiente). Uma aplicação critica pode restringir-se apenas a eventos temporais
- Tarefas apenas interagem através de memória partilhada, em que as actualizações nessa memória têm que ser atómicas
- Depois de iniciar execução uma tarefa não pode suspender ou ficar bloqueada
- Para isso o perfil Ravenscar permite:
- Tarefas para as actividades
- delay until para libertar tarefas periódicas
- Synchronous Task Control para libertar tarefas esporádicas
- Objectos protegidos para libertar tarefas esporádicas, com passagem de informação
- Objectos protegidos para memória partilhada
- Estes dois tipos de objectos protegidos têm que ser independentes, não convém usar um só objecto para duas operações diferentes
- O que faz com que seja fácil definir templates
Introdução à programação em Ada 2005 Pág. 43
Luís Miguel Pinho – Instituto Superior de Engenharia do Porto Outubro de 2006
- Tarefas periódicas
- Tarefas esporádicas
task body Cyclic is Next_Period : Ada.Real_Time.Time := First_Release; Period : Ada.Real_Time.Time_Span :=
Ada.Real_Time.Milliseconds(50); -- declaracoes begin -- Inicializacao loop delay until Next_Period; -- Codigo para a tarefa Next_Period := Next_Period + Period; end loop; end Cyclic;
So: Ada.Synchronous_Task_Control.Suspensaion_Object; -- tem que ser declarado com with task body Sporadic is -- Declaracoes begin -- Inicializacao loop Ada.Synchronous_Task_Control.Suspend_Until_True (So); -- Codigo da tarefa end loop; end Sporadic;
Introdução à programação em Ada 2005 Pág. 44
Luís Miguel Pinho – Instituto Superior de Engenharia do Porto Outubro de 2006
- Dados partilhados
- Esporádico com dados
protected Shared_Data is function Get return Data; procedure Put (D : in Data ); private Current : Data; end Shared_Data; protected body Shared_Data is function Get return Data is begin return Current; end Get; procedure Put (D : in Data ) is begin Current := D; end Put; end Shared_Data;
protected type Event is entry Wait (D : out Data); procedure Signal (D : in Data ); private Current : Data; Signalled : Boolean := False; end Event; protected body Event is entry Wait ( D : out Data ) when Signalled is begin D := Current; Signalled := False; end Wait; procedure Signal ( D : in Data ) is begin Current := D; Signalled := True; end Signal; end Event;
E: Event; task body Sporadic is D: Data; begin -- Inicializacao loop E.Wait(D); -- Codigo da tarefa end loop; end Sporadic;
Introdução à programação em Ada 2005 Pág. 45
Luís Miguel Pinho – Instituto Superior de Engenharia do Porto Outubro de 2006
- Para o 3º módulo de COMPA deve ser analisado o documento (também fornecido):
Alan Burns, Brian Dobbing, George Romanski, “The Ravenscar Tasking Profile for High Integrity Real-Time Programs”, Reliable Software Technologies - Ada-Europe 1998 (http://www.aonix.com/pdf/ravensc.pdf)
- Este documento é importante para perceber os objectivos e restrições do perfil Ravenscar. Está desactualizado na definição de perfil (é anterior à introdução da pragma Profile), mas o que não invalida a discussão do perfil em si.
Introdução à programação em Ada 2005 Pág. 46
Luís Miguel Pinho – Instituto Superior de Engenharia do Porto Outubro de 2006
19. Bibliografia e recursos online
- Bibliografia
1. Introduction to Concurrent Programming, capítulo do livro:
M.B. Feldman, “Software Construction and Data Structures with Ada 95”, Addison-Wesley, 1997 (http://www.seas.gwu.edu/~mfeldman/cs2-book/)
2. Ada 2005 Rationale (http://adaic.org/standards/05rat/html/Rat-
TOC.html) 3. Alan Burns, Brian Dobbing, George Romanski, “The Ravenscar
Tasking Profile for High Integrity Real-Time Programs”, Reliable Software Technologies - Ada-Europe 1998 (http://www.aonix.com/pdf/ravensc.pdf)
4. Burns & Wellings, “Concurrency in Ada 95”, Cambridge Press,
1998
5. Programming in Ada 2005, John Barnes, Addison Wesley, 2006
- Outros recursos online
- Ada Tools and resources: http://www.adapower.com/
- Normas: http://www.adaic.org/standards/
- Ada Annotated Reference Manual (a norma anotada)
- Ada Rationale (explicação das decisões tomadas na linguagem)
- Compilador GNAT: http://libre.adacore.com/