Remote Procedure Call (RPC) e Rendezvous Com troca de mensagens, a programacao de programas do tipo cliente-servidor exigem a troca explicita de duas mensagens Se os canais forem unidirecionais, precisamos de vários canais, e vários testes para detectar o tipo de mensagem. RPC e Rendezvous RPC e Rendezvous são ideais para interações do tipo cliente-servidor. Combinam aspectos de monitores e de troca de mensagens síncronas RPC e Rendezvous Como monitores, um [módulo/]processo exporta operações, que são chamadas a partir de outros [módulos/]processos. Como troca de mensagens síncronas, o processo que faz a chamada bloqueia até que ela seja atendida. A comunicação é bidirecional RPC e Rendezvous A diferença entre RPC e rendezvous é apenas em como as solicitações são atendidas. RPC: procedimentos atendem as chamadas, criando um “processo” para cada solicitação Rendezvous: encontro com um processo que está rodando, através de “accept”. Exemplo de Rendezvous: Ada US DOD criada para ser a linguagem padrão para o desenvolvimento de softwares críticos Sistema de tipos fortes Packages Suporte direto a concorrência: tasks expressibilidade vs. eficiência Rendezvous Comunicação síncrona (sem buffers) duas tasks se encontram em um rendezvous para se comunicarem o primeiro a chegar espera pelo outro accepting task é a dona do rendezvous calling task tem que saber a identidade da accepting task o nome do local do rendezvous Rendezvous modelo assimétrico bom para programar processos servidores partes de uma task em Ada specification entries body task task Buffer is entry Append(I: in Integer); entry Take (I: out Integer); end Buffer; task task body Buffer is begin ... accept Append(I : in Integer) do ... corpo do accept end Append; ... end Buffer; Buffer.Append(I); Rendezvous calling task passa o seu parâmetro in para a accepting task e espera o rendezvous se completar accepting task executa os comandos no corpo do accept (até o end) os parâmetros out são passados de volta à calling task o rendezvous está terminado e as duas tasks não estão mais suspensas Buffer Degenerado task body Buffer is B: Array (0..N-1) of Integer; In_Ptr, Out_Ptr: Integer := 0; Count: Integer := 0; begin loop accept Append(I: in Integer) do B(In_Ptr) := I; end Append; Count := Count + 1; In_Ptr := (In_Ptr + 1) mod N; accept Take(I: out Integer) do I := B(Out_Ptr); end Take; Count := Count - 1; Out_Ptr := (Out_Ptr + 1) mod N; end loop; end Buffer; rendezvous em Ada é uma primitiva com as seguintes caracterísiticas comunicação síncrona e não bufferizada identificação assimétrica fluxo de dados nas duas direções durante o rendezvous O select task body Buffer is ... begin loop select when Count < N => accept Append(I: in Integer) do B(In_Ptr) := I; end Append; Count := Count + 1; In_Ptr := (In_Ptr + 1) mod N; or when Count > 0 => accept Take(I: out Integer) do I := B(Out_Ptr); end Take; Count := Count - 1; Out_Ptr := (Out_Ptr + 1) mod N; end select; end loop; end Buffer; Semântica do select guardas são avaliadas, gerando o conjunto de alternativas abertas tem que haver pelo menos uma, ou um else se há tasks em fila esperando por entries em alternativas abertas, rendezvous é iniciado com a primeira de uma das filas Semântica do select Se todas as filas de espera em alternativas abertas estão vazias, a accepting task é suspensa até que uma task chame uma entrada em uma dessas filas o conjunto de alternativas abertas não muda O select pode ter como última alternativa else ... delay T ... terminate Programando com rendezvous rendezvous implementa remote procedure call delay implementa timeout else implementa polling sincronização com accept bodies vazios Simulando Semáforo task body Semaphore is ... begin loop accept Wait; accept Signal; end loop; end Buffer; Poder de expressão do rendezvous sincronizar múltiplas tarefas accepts aninhados task body T1 is ... begin ... accept Synch_2 do accept Synch_3; end Synch_2; ... end T1; Leitores e escritores task body Readers_and_Writers is ... begin accept Start_Write; accept End_Write; loop select accept Start_Read ...; or accept End_Read ...; or accept Start_Write ...; or accept End_Write ...; end select; end loop; end Readers_and_Writers; Múltiplos accepts task body Even_Odd is ... begin loop accept E(...) do -- process odd calls end E; accept E(...) do -- process even calls end E; end loop; end Even_Odd; uso de select na calling task calling task só pode suspender em uma entry task body T is ... begin loop select Sensor.Sample(...); or delay 1.0; -- seconds Notify_Operator; end select; end loop; end T; Polling vários servidores task body T is ... begin loop select Server_1.E(...); else null; end select; select Server_2.E(...); else null; end select; ... end loop; end T; Polling um servidor task body T is ... begin loop select Server_1.E(...); else select Server_2.E(...); else ...; end select; end select; end loop; end T; Entry Families Type Priorities is (Low, Medium, High); task Server is entry Request(Priorities)(...); end Server; task body Server is begin loop select accept Request(High)(...) ...; or when Request(High)’Count = 0 => accept Request(Medium)(...) ...; or when Request(High)’Count = 0 and Request(Medium)(...)’Count = 0 => accept Request(Low)(...) ...; end select; end loop; end Server;