Requisiti
Realizzazione di un simulatore di un sistema (denominato firefly3SYNC) costituito da 3 lucciole.
Il comportamento deve evolvere in due fasi:
- Primi 10 secondi: lampeggio a frequenza costante propria (asincrono).
- Successivamente: lampeggio in maniera sincrona.
Analisi dei Requisiti
- Identità: Il sistema è un'astrazione di attori interagenti.
- Lucciola (Firefly): Un attore capace di emettere segnali visivi (ON/OFF) e di ricevere stimoli esterni.
- Fase Asincrona: Ogni attore deve possedere un meccanismo di timing interno indipendente.
- Fase Sincrona: Gli attori devono allineare i propri cicli di accensione eliminando i drift temporali.
- Osservabilità: Necessità di un display esterno per verificare lo stato della simulazione.
Analisi del Problema
Architettura del Sistema
Il sistema è logicamente diviso in due contesti distribuiti:
ctxfirefly (localhost:8040): contiene la logica di controllo (coordinatore e lucciole).ctxgrid (127.0.0.1:8050): contiene l'attore esternogriddisplay per la visualizzazione.
Il problema della sincronizzazione
Se ogni lucciola utilizzasse un timer locale (es. whenTime), piccole differenze di scheduling del sistema operativo causerebbero sfasamenti che si accumulano nel tempo.
Il core problem è che non esiste un meccanismo intrinseco negli attori indipendenti per rimettersi in fase.
Decisione Analitica: Per garantire la sincronia perfetta, è necessario passare da un modello a "timer distribuiti" a un modello a "clock centralizzato".
Progetto
Il Coordinator come Direttore d'Orchestra
La scelta progettuale chiave è l'introduzione di un unico attore centralizzato, il
QActor coordinatorcontext ctxfirefly {State s0initial {delay 10000// 10 secondi di fase asincrona iniziale }Goto loopState loop {emit sync : sync(1)// Segnale simultaneo per tutti delay 1500 }Goto loop }
Firefly: Attori Puramente Reattivi
Le lucciole vengono modellate come entità prive di stato temporale proprio nella fase di regime, rendendole dipendenti dal segnale
State wait_sync { }Transition t0whenEvent sync -> flashState flash {forward griddisplay -m cellstate : cellstate($X, $Y, 1)delay 500forward griddisplay -m cellstate : cellstate($X, $Y, 0) }Goto wait_sync
Vantaggi della soluzione
- Precisione: Tutte le lucciole ricevono l'evento nello stesso istante logico.
- Scalabilità: Il
coordinator emette un singolo segnale senza dover conoscere il numero o l'identità dei destinatari. Aggiungere lucciole non richiede modifiche al codice del coordinatore. - Separazione delle responsabilità: La comunicazione verso il display rimane punto-punto (dispatch), mentre la sincronizzazione usa il broadcast.