5 THE DATA SET
5.5 Taxation and Depreciation
Na nossa estratégia de tradução, canais que comunicam n valores e são usados pelo menos uma vez em multi-sincronização serão arrays n-dimensionais de GeneralChannel, em que cada índice de dimensão representa um valor comunicado. Se um dado canal chan comunica dois valores, por exemplo, a sua tradução será como segue:
channel chan : Z x Z⇒ GeneralChannel [][] chan;
A seta (⇒) estabelece uma relação entre a declaração do canal na especificação a ser traduzida, e a declaração do canal no código a ser gerado. Cada índice do array de
GeneralChannel corresponde ao valor absoluto de um valor comunicado. Por exem-
channel chan : {-4, -2, 0, 2}
process J= beginb
• chan.(-2) → SKIP end
os valores absolutos dos valores comunicáveis de chan serão: 0 para o valor -4, 1 para o valor -2, 2 para o valor 0, e 3 para o valor 2. Na tradução, cada canal terá uma classe, chamada Abs < nome do canal >, que armazenará um mapa que mapeia valores co- municáveis aos seus valores absolutos. Assim, para o canal chan da especificação do processo J , -4 será mapeado a 0, -2 será mapeado a 1, e assim por diante.
Na migração ao novo JCSP, comunicações de canais serão traduzidas como execuções do método sync do front-end end em uma posição de um array de GeneralChannel. Os valores absolutos dos valores comunicados pelo canal serão os índices das dimensões do array de GeneralChannel, como segue:
chan.(-4) ⇒ chan [Abs chan.abs (−4)].sync();
em que ⇒ simboliza uma relação entre a comunicação na especificação, e a comuni- cação na tradução. chan.(−4) é uma comunicação com um campo pontual que tem o valor -4. É bom salientar que o método sync, em chan [Abs chan.abs (−4)] é a invo- cação do método sync do front-end end, que é atributo de GeneralChannel.
Devido ao número de campos de comunicação arbitrário que os canais podem ter, depen- dendo da especificação, os canais traduzidos podem ter um número variado de dimensões em suas declarações. Isto faz com que getProcessSyncEnds deva receber como parâmetro um array n-dimensional de GeneralChannel, o que torna a sua implementação não- trivial. A implementação de getProcessSyncEnds deve variar de acordo com o número de dimensões do canal. Assim, ela foi feita implementando-se um gerador de sobrecarga de método, chamado GPSEGenerator. Para cada especificação, GPSEGenerator gera implementações de getProcessSyncEnds da dimensão 0 até a máxima dimensão de um canal daquela especificação. Estas implementações de getProcessSyncEnds serão en- capsuladas numa classe, gerada por GPSEGenerator, chamada GPSE . Cada implemen- tação de GPSE (não importa a dimensão do canal) possui um método chamado index -
Of End Part, que determina o índice de uma dimensão de um array de GeneralChannel.
O método index Of EndPart tem 4 parâmetros: o primeiro é a posição do canal, o se- gundo é a dimensão do canal, o terceiro é o número de dimensões do canal, e o quarto é o número de valores comunicáveis pelo canal. A figura 3.1 ilustra o funcionamento de indexOfEndPart. Na figura 3.1, b[1][2] é a quinta possibilidade de comunicação do
GeneralChannel b. Aqui, chamaremos cada uma destas possibilidades de "posições do
GeneralChannel". Os valores das dimensões de b[1][2] são 1 e 2. O número de dimensões
de b é 2, e o número de valores comunicáveis por b é 3 (de 0 a 2). Assim sendo, temos que
Figura 3.1: Esquema explicativo do método indexOfEndPart
indexOfEndPart (5, 1, 2, 3) = 2.
O método indexOfEndPart deverá ser usado por cada sobrecarga de getProcessSyncEnds para determinar os índices das dimensões do GeneralChannel. Para o caso em que a di- mensão máxima de um canal na especificação a ser traduzida é 2, uma sobrecarga do método getProcessSyncEnds é a seguinte:
public static GeneralChannel [][] getProcessSyncEnds (int x, GeneralChannel [][] gc) {
GeneralChannel [][] b = new GeneralChannel [3][3]; for (int i = 0; i < numberOfEnds(); i++) {
int d0 = indexOfEndPart (i, 0, 2, 3); int d1 = indexOfEndPart (i, 1, 2, 3);
ChanInfo channelInfo = gc[0][0].getChannelInfo();
b [d0][d1] = new GeneralChannel (channelInfo, channelInfo.get(x)); b [d0][d1].setEnd (gc [d0][d1].getBarrier () [channelInfo.get(x)]); }
return b; }
Na sobrecarga de getProcessSyncEnds exibida anteriormente, o método numberOfEnds calcula o número de possibilidades de comunicação ("posições do GeneralChannel") para um GeneralChannel, de acordo com o seu número de dimensões e o número de valores comunicáveis pelo canal (aqui é importante fazer uma distinção: as possibilidades de co- municação a que nos referimos não são os valores comunicáveis. Por exemplo, um canal que comunica dois valores de um tipo de conjunto com dois elementos terá 2 valores co- municáveis, e 4 (2x2) possibilidades de comunicação). O método getChannelInfo retorna um objeto do tipo ChanInfo. Este objeto possui um mapa hash que mapeia os identifi- cadores dos processos matriculados no canal aos seus índices de front-end no canal.
Como as posições do array de GeneralChannel devem ter o mesmo conteúdo, escolheu- se, por questões de praticidade, a posição de origem (gc [0], gc [0][0], gc [0][0][0], e etc) como default para ser colocada como parâmetro da instanciação de GeneralChannel.
ChanInfo e getChannelInfo foram implementados por [Freitas 2005], na estratégia de
tradução do estado original deJCircus. A tradução do processo P da seção 3.2.3 em JCSP
é apresentada a seguir.
public class P implements CSProcess { private GeneralChannel a;
public P (GeneralChannel a) { this.a = a;
}
public void run () { (new CSProcess () {
public void run () { a.sync();
(new Skip ()).run(); }
}).run(); }
}
No processo P do código-fonte anterior, pode-se observar a declaração do atributo a, do tipo GeneralChannel. Todos os canais visíveis de um processo deverão ser declarados, no código traduzido, como atributos, e inicializados na instanciação do processo, que deverá receber o canal como parâmetro. A ocorrência do evento a, na tradução, ocorre pela invocação do seu método sync.
O procedimento descrito até agora com sincronização através de barreiras alternantes é utilizado quando houver uma ou mais multi-sincronizações envolvendo o canal. Nem sempre, no entanto, para um dado canal, ocorre uma multi-sincronização, e dentro de mais algumas exigências (a serem descritas na próxima sub-seção), a utilização de barreiras alternantes se torna desnecessária. A seção a seguir explica em que condições o uso de barreiras alternantes se torna desnecessário.