• Non ci sono risultati.

Reo Coordination Language [130] costituisce uno dei temi di ricerca pi`u at- tivi del gruppo SEN3 del Centro per la Matematica e l’Informatica [103]. Le prime pubblicazioni sul linguaggio risalgono approssimativamente al 2002 [10] e la ricerca su Reo viene tuttora portata avanti.

Reo `e un linguaggio di coordinamento “esogeno” basato su canali, in cui `e possibile modellare coordinatori complessi, detti connettori, in maniera com- posizionale a partire da coordinatori pi`u semplici [5]. L’aggettivo “esogeno” (exogenous) si riferisce al fatto che il linguaggio modella coordinamenti tra componenti, senza alcuna conoscenza della loro struttura interna e senza che i componenti stessi abbiano visione del coordinamento che si sta realizzando. Questa caratteristica permette di concentrarsi su una prospettiva incentrata sui dati.

Reo inoltre `e “channel-based”, nel senso che i canali, come discuteremo in seguito, costituiscono gli elementi di base del linguaggio per la realizzazione di modelli di coordinamento dei componenti.

ro come linguaggio per “incollare” insieme componenti diverse e costruire in maniera composizionale connettori addetti all’orchestrazione di componenti o servizi ad esempio in un’applicazione orientata ai servizi.

Vediamo alcune delle caratteristiche principali offerte dal linguaggio Reo: • Accoppiamento lasco tra componenti e servizi.

• Supporto alla distribuzione e mobilit`a di componenti eterogenei. • Coordinamento esogeno, dunque realizzato da terze parti. • Modellazione composizionale.

• Modellazione mista di comunicazioni sincrone e asincrone. • Possibilit`a per l’utente di definire nuove primitive.

• Notazione grafica analoga ai circuiti elettrici.

• Semantica formale basata su Constraint Automata (CA). • Metodi di specifica e verifica basati su programmazione logica.

Il risultato derivante dall’utilizzo di Reo per la modellazione di sistemi di coordinamento `e il connettore. In terminologia Reo, un connettore `e un coordinatore esogeno che si occupa dell’orchestrazione dei componenti che fanno parte del sistema composto che si sta modellando. Un connettore `e costituito da un opportuno insieme di canali, che rappresentano dunque gli elementi di base per la creazione di coordinatori complessi. I canali possono essere visti come dei connettori elementari, di fatto sono gli unici connettori primitivi in Reo e rappresentano un mezzo di comunicazione punto a punto

tra due distinte entit`a. Reo mette a disposizione un insieme di comuni tipolo- gie di canali, ai quali `e possibile affiancare eventuali canali definiti dall’utente in base al comportamento desiderato. La creazione di connettori complessi avviene attraverso la composizione di canali abbinata all’utilizzo di nodi (che descriveremo pi`u avanti).

Di per s´e un canale non ha una direzione associata, ma comprende due estre- mit`a dirette (directed ends), attraverso le quali i componenti possono effet- tuare operazioni sul canale e sui dati che eventualmente contiene. Infatti i canali in Reo vengono utilizzati esclusivamente per trasferire dati attraverso le operazioni di input/output realizzate sulle loro estremit`a (channel ends). I canali possono avere due tipi di estremit`a: sorgenti e pozzi. Una sorgen- te (source channel end) accetta dati da trasmettere all’interno del proprio canale, mentre un pozzo (sink channel end) distribuisce dati all’esterno del canale.

In Figura 4.15 sono rappresentati i principali canali di base presenti in Reo:

Fig. 4.15: Principali tipologie di canali Reo

• Sync. Un canale di tipo Sync `e caratterizzato dalla presenza di un’e- stremit`a sorgente, un’estremit`a pozzo e non contiene buffer per la me- morizzazione dei dati. Il suo comportamento `e definito nel seguente

modo: accetta di ricevere dati attraverso l’estremit`a sorgente solo se al- lo stesso tempo `e in grado di inoltrarli all’esterno attraverso l’estremit`a pozzo. L’estremit`a pozzo `e quella indicata con la freccia.

• LossySync. Un canale di tipo LossySync esibisce un comportamento analogo a quello del canale Sync. La differenza che li distingue `e che in un canale LossySync, nel caso in cui non sia possibile inoltrare i dati all’esterno, ovvero nel caso in cui l’elemento collegato al pozzo non sia pronto ad accettare informazioni, i dati presenti nel canale vengono perduti.

• FIFO1. Un canale di tipo FIFO1 `e un canale asincrono con una sorgen- te ed un pozzo, dotato di una cella di memoria nella quale (compatibil- mente con la disponibilit`a all’interno della cella) vengono memorizzati i dati che arrivano alla sorgente.

• SyncDrain. Un canale di tipo SyncDrain `e caratterizzato da due sor- genti, pertanto il suo comportamento `e quello di accettare dati da en- trambe le estremit`a. Il flusso di dati `e possibile solo se entrambe le estremit`a sono pronte a trasmettere. Dal momento che il canale non presenta alcun pozzo, i dati che transitano all’interno vengono perduti. • AsyncDrain. Un canale di tipo AsyncDrain ha le stesse estremit`a di un canale SyncDrain, ma il suo comportamento si differenzia per via della caratteristica che lo porta ad accettare dati solo da una delle due estremit`a allo stesso tempo. Dunque non si pu`o verificare il passaggio di dati contemporaneo da entrambe le sorgenti.

• Filter(P). Un canale di tipo Filter effettua una selezione sui dati che transitano attraverso le sue estremit`a. In particolare, per mezzo del pat- tern P che gli `e associato, `e possibile specificare quali dei dati ricevuti saranno trasmessi all’estremit`a pozzo e dunque fluiranno all’esterno. I dati che non soddisfano la condizione espressa da P verranno comun- que accettati attraverso la sorgente ma verranno persi all’interno del canale.

• SyncSpout(P). Un canale di tipo SyncSpout `e caratterizzato da due pozzi, pertanto il suo comportamento `e quello di dispensare dati da entrambe le estremit`a. Ciascun pozzo produce una quantit`a illimitata di dati che rispettano il pattern P associato al canale. Il flusso di dati `

e possibile solo simultaneamente da entrambe le estremit`a.

• AsyncSpout(P). Un canale di tipo AsyncSpout ha le stesse estremit`a di un canale SyncSpout, ma il suo comportamento si differenzia per via della caratteristica che lo porta a dispensare dati solo da una delle due estremit`a allo stesso tempo. Dunque non si pu`o verificare il passaggio di dati contemporaneo da entrambi i pozzi. Anche in questo caso i dati prodotti soddisfano il pattern P associato al canale.

L’operazione di composizione dei canali, siano essi di base o definiti dall’u- tente, avviene congiungendo le loro estremit`a che vengono in questo modo a formare dei nodi. Un nodo dunque rappresenta la convergenza di un insieme di estremit`a di canali. Un nodo pu`o raggruppare un numero arbitrario di estremit`a di canali e la sua struttura ha delle implicazioni dirette su come il flusso viene diretto e ripartito tra i canali che fanno capo al nodo in questio-

ne.

In base alla tipologia di estremit`a che convergono su di essi, i nodi possono essere classificati in tre diverse categorie:

• Nodi sorgente. Un nodo sorgente o di input (source/input node) `

e determinato dal congiungimento di sole estremit`a sorgente. I com- ponenti possono collegarsi a nodi sorgente per eseguire operazioni di input. Un’operazione di scrittura eseguita da un componente connesso ad un nodo sorgente pu`o essere realizzata con successo solo se tutte le estremit`a raggruppate sono pronte a ricevere dati. In tal caso le infor- mazioni inviate dal componente vengono replicate su tutte le sorgenti che fanno capo al nodo. Dunque di fatto un nodo sorgente si comporta come un “replicatore” di dati (replicator).

• Nodi pozzo. Un nodo pozzo o di output (sink/output node) `e determi- nato dal congiungimento di sole estremit`a pozzo. I componenti possono collegarsi a nodi pozzo per eseguire operazioni di output. Un’operazio- ne di lettura eseguita da un componente connesso ad un nodo pozzo pu`o essere realizzata con successo solo se almeno una delle estremit`a raggruppate `e pronta ad inviare dati. Nel caso in cui pi`u di un’estre- mit`a fosse disposta ad inviare dati, ne viene selezionata una in maniera nondeterministica. Dunque di fatto un nodo pozzo esegue una fusione nondeterministica dei dati ricevuti (nondeterministic merge).

• Nodi misti. Un nodo misto (mixed node) `e determinato dal congiun- gimento di entrambi i tipi di estremit`a, dunque combina le funzionalit`a di un nodo sorgente con quelle di un nodo pozzo. Il comportamento

osservato `e il seguente: seleziona in maniera nondeterministica un’e- stremit`a pozzo pronta ad inviare dati, esegue l’operazione di lettura e replica il contenuto dei dati su ciascuna delle estremit`a sorgente. Un dato proveniente da un’estremit`a pozzo pu`o essere letto e inoltrato solo se tutte le estremit`a sorgente che fanno capo al nodo sono disposte ad accettarlo.

La Figura 4.16 illustra i diversi tipi di nodo esistenti in Reo. Come gi`a ac-

Fig. 4.16: Nodi Reo: sorgenti (a, b), pozzi (c, d), misti (e)

cennato, `e possibile utilizzare connettori semplici per costruirne degli altri pi`u complessi attraverso una modalit`a di tipo composizionale. La creazione di un nuovo connettore avviene per mezzo dell’operazione di unione (join) [4]. L’unione di due nodi provoca la distruzione di entrambi e la conseguente creazione di un nuovo nodo sul quale convergono tutte le estremit`a preceden- temente connesse ai due nodi di partenza.

Un connettore `e definito come un insieme di estremit`a di canali organizzate in una struttura a grafo. La struttura risultante contiene un insieme di nodi ed archi che rispettano le seguenti propriet`a:

• su ciascun nodo del grafo convergono zero o pi`u estremit`a di canali; • ciascuna estremit`a di canale converge su esattamente un nodo;

• un arco tra due nodi pu`o esistere se e solo se esiste un canale tale che ciascuna delle estremit`a converge su uno dei due nodi (il canale unisce i due nodi).

Presentiamo di seguito alcuni esempi di connettori Reo. Il connettore in Fi-

Fig. 4.17: Router esclusivo (a) e notazione alternativa (b)

gura 4.17 illustra la rete Reo che modella un instradatore esclusivo (exclusive router), che implementa una politica in stile XOR sul flusso in entrata. La rete `e composta da canali Sync, LossySync ed un canale di tipo SyncDrain. Il connettore router esclusivo inoltra i dati resi disponibili dal nodo sorgente A ad esattamente uno dei nodi pozzo B e C, in base alla loro disponibilit`a di accettare dati o meno. Dunque se solo uno dei due nodi `e pronto a ricevere, i dati ricevuti dal nodo A verranno inoltrati al nodo in questione. Se entram- bi i nodi pozzo B e C sono disposti a ricevere i dati, allora attraverso l’uso del nodo S verr`a scelto in maniera nondeterministica il nodo a cui verranno inoltrati i dati, mentre l’ulteriore copia dei dati verr`a assorbita dal canale LossySync.

E’ opportuno specificare che il riquadro che circonda il router esclusivo il- lustrato in Figura 4.17 rappresenta graficamente la cosiddetta operazione di

“hide” (occultamento), attraverso la quale `e possibile occultare i dettagli re- lativi ai nodi di un connettore e alla topologia dei canali. In questo modo sar`a possibile connettersi ai nodi di input/output A, B e C, ma tutte le altre informazioni sulla struttura interna del connettore verranno nascoste. L’ope- razione di hide fornisce un potente e importante meccanismo di astrazione: nascondendo uno o pi`u nodi si assicura che la topologia di tali nodi non potr`a essere modificata in alcun modo e allo stesso tempo si continua a garantire l’utilizzo del connettore attraverso le altre operazioni.

In Figura 4.17 `e rappresentata anche una notazione alternativa per il con- nettore router esclusivo, che viene raffigurato con un simbolo simile a quello utilizzato per i nodi. Visto il frequente utilizzo del connettore router esclu- sivo si `e resa necessaria una notazione alternativa che permettesse una sua rappresentazione agile, risparmiando al modellatore l’onere di riscriverlo ad ogni utilizzo. Come si pu`o osservare in figura, il connettore XOR pu`o essere esteso ad un numero arbitrario di nodi pozzo.

Proponiamo un altro esempio di connettore, ovvero il “sequencer” (sequenzia- lizzatore), illustrato in Figura 4.18, utilizzato per imporre un preciso proto- collo di sequenzializzazione. Notiamo che il connettore `e costituito da cinque

nodi, tre dei quali sono nodi di output (indicati in figura come A, B e C). Diciamo che il sequencer esprime un protocollo di sequenzializzazione poich´e le operazioni di ricezione dei dati da parte dei nodi pozzo, possono essere ese- guite con successo solo nell’ordine da sinistra a destra, ovvero A per primo, quindi B ed infine C. Osserviamo che la presenza di un token all’interno del canale FIFO1 a estrema sinistra indica che il buffer `e inizializzato con dei dati.

Anche il sequencer, cos`ı come il router esclusivo, pu`o essere esteso ad un numero arbitrario di nodi di output. In questo caso `e sufficiente estendere il connettore con ulteriori coppie di canali FIFO1 e Sync da agganciare al connettore.