5 \includegraphics[width=
14cm
]{Attivita_Concorrenza_Circuito
}
6 \caption{Protocollo di percorrenza del circuito.
}
9 \section{Percorrenza del circuito: Sector e Lane
}
10 %---------forse da mettere nella descrizione di track
11 \textit{Track
} è un entità passiva, in particolare una
\textit{RCI
}.
12 In
\textit{Track
} sono presenti le entità protette
\textit{Sector
} e
\textit{Lane
}, che rappresentano gli elementi della pista.
13 La pista è divisa in settori, intesi come rettilinei, curve o box. Ogni settore può essere un intertempo, ovvero essere dotato degli strumenti per tenere traccia dei tempi di percorrenza.
14 La pista non è altro che un insieme ordinato (nello specifico un
\textit{array
}) di settori, a cui si aggiunge il settore dei box.
18 \textit{Sector
} è implementato come una risorsa protetta: viene ipotizzato quindi che le auto possano entrare (e uscire) una alla volta in un determinato settore.
19 Questa assunzione, anche se non rispecchia esattamente la realtà, consente una gestione più semplice e corretta della concorrenza, come si vedrà in seguito.
20 Ogni
\textit{Sector
} si compone di un certo numero di corsie parallele che possono essere percorse contemporaneamente da più autovetture, chiamate
\textit{Lane
}.
21 Segue lo pseudocodice della procedura di entrata in un settore.
23 \begin{lstlisting
}[frame=trBL,columns=fixed,postbreak=
\space,breaklines,caption=
{Procedura Enter di Sector.
}]
27 n_lane := corsia da percorrere. Trovo quella meno trafficata.
28 aggiorno variabili di Sector notificando l'ingresso nel settore n_lane
30 requeue Corsie(Sector_Id)(n_lane).Demand;
35 Il compito principale della risorsa
\textit{Sector
} è quello di smistare le auto in ingresso nelle varie corsie secondo una logica predefinita.
38 \textit{Lane
} è implementato anch'esso come una risorsa protetta. Esso calcola, a partire dal tempo di invocazione e dalle caratteristiche dell'auto in questione, il tempo di percorrenza del tratto. Vengono eseguiti controlli sul valore calcolato, in modo da evitare i sorpassi nello stesso
\textit{Lane
}.
39 Segue il codice semplificato della procedura di accesso alla corsia.
41 \begin{lstlisting
}[frame=trBL,columns=fixed,postbreak=
\space,breaklines,caption=
{Procedura principale di Lane.
}]
42 entry Demand (time : Time) is
43 -- ExitTime : variabile di Lane che salva il tempo d'uscita piu' alto tra le auto che precedono
44 -- ExitSpeed : variabile di Lane che salva la velocita' d'uscita dell'auto con tempo d'uscita piu' alto.
46 t, speed := CalculateDriveTime;
47 -- la chiamata ritorna il tempo di percorrenza e la velocita' calcolati
51 -- se non ci sono auto che precedono, salvo i valori nelle variabili di Lane
52 if (time > exit_time) then
55 elsif (time < exit_time) then
56 -- se sono presenti altre auto nel Lane, vengono modificati tempo di uscita e velocita'
58 if (speed > exit_speed) then speed:=exit_speed;
65 Il trasferimento della chiamata da
\textit{Sector
} a
\textit{Lane
} verrà implementato con
\textit{requeue
}. Questo permette di liberare la risorsa
\textit{Sector
} durante il calcolo dei tempi di percorrenza, non pregiudicando la correttezza poichè il protocollo di accesso al circuito prevede di dover invocare
\textit{Sector
} e non
\textit{Lane
}. Il protocollo non presenta quindi situazioni di race condition non gestite.
68 Queste scelte architetturali consentono a più auto di percorrere contemporaneamente lo stesso settore, consentendo quindi anche il sorpasso. Inoltre più auto possono percorrere contemporaneamente lo stesso
\textit{Lane
}, ma in questo caso non è consentito alle auto di superarsi.
70 \subsection{Release
\_and\_Enter}
71 Nella figura
\ref{fig:attivita
} è rappresentato il protocollo di percorrenza del circuito. Come si vede, la chiamata a
\textit{Release
\_and\_Enter}, che fa uscire un auto da un settore e la fa automaticamente entrare nel settore successivo, ritorna un valore
\textit{Time
}, che indica il tempo al quale l'auto avrà terminato di percorrere quel tratto. L'auto eseguirà quindi una chiamata
\texttt{delay until Time;
}, ma prima dovrà comunicare questo tempo di uscita al settore interessato attraverso la procedura
\textit{BookExit
} con parametro
\textit{Time
}. Scaduto questo tempo, l'auto è pronta per percorrere il settore successivo, seguendo la stessa procedura.
74 La scelta di rendere atomiche l'uscita da un settore e l'entrata nel successivo è dovuta al fatto che, tenendo le procedure separate e ritornando il controllo al chiamante di
\textit{PutOnPitLane
}, non sarebbe stato possibile sempre prevedere l'ordine di esecuzione, cioè l'ordine di ingresso nel settore successivo. Inoltre piccole differenze nei tempi di risveglio dalla
\textit{delay until
} potrebbero portare a sorpassi indesiderati.
76 La scelta di tenere la procedura
\textit{BookExit
} esterna, invece che invocarla automaticamente dalla
\textit{Release
\_and\_Enter} è stata fatta per la maggior semplicità nel protocollo di ritiro delle auto.
78 Segue il codice semplificato del protocollo di riaccodamento.
80 \begin{lstlisting
}[frame=trBL,columns=fixed,postbreak=
\space,breaklines,caption=
{Procedura principale di Sector.
}]
83 entry Release_and_Enter
84 --ExitArray e' una struttura dati che per ogni auto ha un flag booleano Arrived che ne segna l'arrivo
86 if (ExitArray(
1).CarId = my_properties.CarId) then
87 -- l'auto e' la prima nella lista di uscita
88 rimuovi l'auto da ExitArray
89 if (sono presenti auto nella coda interna) then
96 -- l'auto NON e' la prima nella lista di uscita: la chiamata deve essere trasferita nella coda interna ExitLane
97 ExitArray(posizione auto) := True;
98 chiudi la guardia di ExitLane
99 -- trasferisco la chiamata in ExitLane
103 next_sect := calcolo il settore successivo
104 requeue Sectors(next_sect).Enter;
105 end Release_and_Enter;
108 \subsubsection{Uscita dal settore
}
109 La procedura
\textit{Release
\_and\_Enter} utilizza il modello a guscio d'uovo per gestire l'ordine di uscita dal settore. Se infatti un'auto invoca
\textit{Release
\_and\_Enter} quando ancora non è il suo turno di uscita (l'ordine è conosciuto e mantenuto coerente in una struttura dati interna a
\textit{Sector
}), la chiamata viene trasferita in una coda interna, governata da una guardia di Dijkstra, fino a quando la procedura non verrà invocata da un'altra auto. Se è quest'ultima l'auto che deve uscire, viene aperta la guardia della coda interna e le auto in attesa vengono fatte uscire, sempre rispettando l'ordine. Altrimenti anche questa seconda auto viene accodata nella coda interna.
110 Di seguito vediamo il codice semplificato della entry ExitLane.
112 \begin{lstlisting
}[frame=trBL,columns=fixed,postbreak=
\space,breaklines,caption=
{Procedura ExitLane di Sector.
}]
113 entry ExitLane when Changed = True is
115 if (ExitArray(
1).CarId = my_properties.CarId) then
116 -- l'auto e' la prima nella lista di uscita
117 rimuovi auto da ExitArray
118 if (sono presenti auto nella coda interna) then
124 next_sect := calcolo il settore successivo
125 requeue Sectors(next_sect).Enter;
128 -- l'auto NON e' la prima nella coda di uscita
134 In questo modo viene gestito algoritmicamente l'ordine di uscita dai settori.
138 Il componente Race è implementato come un tipo task. Si tratta di un
\textit{server
}, cioè un tipo di entità reattiva. L'esecuzione delle varie chiamate avviene quindi in mutua esclusione. Questo permette di assegnare senza incorrere in
\textit{race condition
} gli
\textit{ID
} alle auto registrate. Inoltre l'esecuzione in mutua esclusione delle chiamate semplifica la gestione delle classifiche e dei monitor.
140 \textit{Race
} infatti ha anche il ruolo di gestione delle statistiche. Logicamente è la gara che conosce la classifica ed i vari tempi di percorrenza sull'intermedio e sul giro dei singoli concorrenti.
\textit{Race
} si occupa quindi di ricevere informazioni sulle percorrenze da
\textit{Track
}, elaborare tali dati ottenendo informazioni derivate (ad esempio il tempo sul giro) e diffondere queste informazioni ai monitor tramite un protocollo di comunicazione che segue il modello della
\textit{push notification
}.
141 Tutte le chiamate relative alle statistiche sono implementate come asincrone.
145 Monitor, per sua natura, è strettamente correlato alla propria GUI. Coerentemente con i messaggi ricevuti da gara, viene creata una struttura dati GTK che ne permette la visualizzazione. La concorrenza in questo componente si limita alla mutua esclusione nell'accesso alla struttura dati, che viene garantita da apposite chiamate GTK con cui racchiudere la sezione critica.
147 \section{Protocollo di partenza
}
148 \label{Protocollo_Partenza
}
149 Il protocollo di partenza emula quello che accade nel mondo reale. Si fissa un ordine di partenza, che può dipendere dall'
\textit{ID
} delle auto o essere randomizzato.
150 Quando arriva il segnale di inizio gara, la prima auto inizia a percorrere il primo settore; in particolare, effettua una chiamata
\textit{Enter
}. Solo a questo punto, l'auto notifica alla successiva che può partire.
151 Il protocollo di partenza ``simula'' l'idea di una fila, in cui ogni auto può partire solo dopo che l'auto precedente è partita.
152 Come tempo di inizio della competizione viene inteso il tempo di partenza della prima auto in griglia. \\
153 Questa soluzione sembra un giusto compromesso tra semplicità e realismo nella simulazione.
156 \section{Correttezza temporale
}
157 \label{Correttezza_Temporale
}
158 Si può assumere che il protocollo di percorrenza del circuito è corretto dal punto di vista temporale sulla base delle seguenti considerazioni:
160 \item La simulazione avviene interamente nel componente
\textit{Track
}. I tempi necessari alla simulazione (tempo di avvio della gara) sono riferiti solo all'orologio locale del nodo in cui esegue questa componente. Non si presentano quindi problemi legati alla sincronizzazione degli orologi. Inoltre i tempi di percorrenza sono tutti relativi (
\textit{Duration
}), quindi completamente indipendenti dall'orologio di sistema.
162 \item L'ordine di ingresso in un settore è controllato da una risorsa protetta (il settore precedente) che ne assicura la correttezza a prescindere dall'ordine di esecuzione.
164 \item I tempi di percorrenza si basano solo sui tempi calcolati, quindi il protocollo è corretto indipendentemente dall'ordine e dal tempo di esecuzione.
166 \item Il tempo di percorrenza di un settore dipende esclusivamente dalle caratteristiche dell'auto e quindi ancora indipendente dall'esecuzione concorrente.
168 \item L'unico caso in cui il tempo calcolato viene modificato è quando la corsia di percorrenza è affollata. In questo condizione il tempo di percorrenza dell'auto viene aumentato in modo che il tempo d'uscita dal settore non sia inferiore di quelli delle auto che precedono, quindi concettualmente corretto.
170 \item L'accodamento nelle varie corsie è controllato algoritmicamente: viene scelta la corsia meno affollata. E' quindi decidibile e non dipende dall'ambiente di esecuzione.
173 I problemi maggiori dipendono dal fatto che i task possono alternarsi nell'esecuzione in modo (per noi) non predicibile. Si sono presentati diverse situazioni che riguardo questa tematica. Di seguito ne elenchiamo alcune, con le relative soluzioni.
176 \item il risveglio delle auto dalla
\textit{delay
} può non avvenire in ordine: la soluzione è stata l'introduzione di un protocollo di
\textit{booking
}: le auto comunicano ai settori quale sarà il loro tempo di uscita. La procedura che implementa questa idea è chiamata
\textit{BookExit
}. Sostanzialmente si tratta di una soluzione algoritmica ad un ordine di esecuzione dei processi non corretto.
177 I processi vengono accodati in una coda interna di una risorsa protetta (
\textit{Sector
}).
178 Le auto riescono ad uscire dal settore solo rispettando l'ordine di uscita calcolato sui tempi comunicati in precedenza.
179 Un task che esegue in un momento non previsto, non ha la possibilità di uscire, viene riaccodato nella coda interna, e deve attendere l'esecuzione degli altri task. Questi task eseguiranno sicuramente, poichè se un'auto intende ritirarsi, non effettuerà la chiamata a
\textit{BookExit
}, quindi non risulterà presente nella lista dei tempi di uscita (esclusa
\textit{starvation
}). Questo protocollo non compromette i tempi di percorrenza.
181 \item Tra l'uscita da un settore e l'entrata nel successivo, l'ordine di esecuzione dei task potrebbe cambiare (prerilascio). La soluzione è stata rendere atomiche l'uscita da un settore e l'entrata nel successivo. L'implementazione prevede una
\textit{requeue
} dal metodo
\textit{Release
} di un settore, al metodo
\textit{Enter
} del settore successivo.
183 \item Coerenza dei tempi: il tempo di calcolo che intercorre tra il risveglio dalla
\textit{delay until
} al calcolo del tempo di risveglio nel settore successivo, non viene tenuto in considerazione.
184 Il tempo di calcolo è quindi irrilevante. Questo tempo di calcolo, anche se fosse molto grande e diverso per ogni auto, non potrebbe in alcun modo influire sull'ordine di percorrenza, sui distacchi o sui tempi sul giro.
185 I tempi sul giro ed i distacchi sono infatti calcolati come somma dei tempi dei singoli settori.
188 La gestione dei tempi di gara sembra risultare corretta e coerente. Auto con le stesse caratteristiche hanno identici tempi di percorrenza (a parte nel primo giro per i tempi di partenza diversi).