UniTO/anno2/YearI/FirstSem/MCAD/bardellostadio.md
Francesco Mecca 5e286062f8 MCAD 2019
2018-11-22 13:09:11 +01:00

7.4 KiB

Semafori

Inizializzazione

semaphore mutex = 1;
semaphore ospiti, locali, pulizia; // iniz. a 0
int nOsp = 0;
int nLoc = 0;
int attesaOspiti = 0;
int attesaLocali = 0;
bool chiusura;

Ospiti

public void entraOspite () {
	P (mutex);
	if (nOsp == NMAX || chiusura) {
		V (mutex);
		attesaOspiti++;
		P (ospiti);
		attesaOspiti--;
	}
	nOsp++;
	if (nOsp < NMAX && !chiusura && attesaOspiti > 0) {
		V (ospiti);
	} else {
		V (mutex);
	}
}
public void esciOspite () {
	P (mutex);
	nOsp--;
	if (attesaOspiti > 0 && !chiusura) {
		V (ospiti);
	} else if (attesaOspiti == 0 && attesaLocali > 0 && nOsp == 0 && !chiusura) {
		V (locali);
	} else if (nOsp == 0 && chiusura) {
		V (pulizia);
	} else {
		V (mutex);
	}
}

Locali

public void entraLocale () {
	P (mutex);
	if (chiusura || nLoc == NMAX || (attesaOspiti > 0 && nLoc == 0)) {
		V (mutex);
		attesaLocali++;
		P (locali);
		attesaLocali--;
	}
	nLoc++;
	if (nLoc < NMAX && !chiusura && attesaLocali > 0) {
		V (locali);
	} else {
		V (mutex);
	}
}
public void esciLocale () {
	P (mutex);
	nLoc--;

	if (nLoc == 0 && !chiusura && attesaOspiti > 0) {
		V (ospiti);
	} else if (attesaLocali > 0 && !chiusura) {
		V (locali);
	} else if (nLoc == 0 && chiusura) {
		V (pulizia);
	} else {
		V (mutex);
	}
}

Barista

public void pulisciBar () {
	P (mutex);
	chiusura = true;
	if (nLoc > 0 || nOsp > 0) {
		V (mutex);
		P (pulizia);
	}
	<...pulisci...>
	chiusura = false;

	if (attesaOspiti > 0) {
		V (ospiti);
	} else if (attesaLocali > 0) {
		V (locali);
	} else {
		V (mutex);
	}
}

Monitor

monitor bar {
	int nLoc = 0;
	int nOsp = 0;
	bool chiusura = false;
	condition locali, ospiti, pulizia;

	public void entraOspite() {
		if (nOsp == NMAX || chiusura) {
			wait (ospiti);
		}
		nOsp++;
		if (nOsp < NMAX && !chiusura && !empty(ospiti)) {
			signal (ospiti);
		}
	}

	public void esciOspite () {
		nOsp--;

		if (!empty(ospiti) > 0 && !chiusura) {
			signal (ospiti);
		} else if (nOsp == 0 && empty(ospiti) == 0 && !empty (locali) > 0 && !chiusura) {
			signal (locali);
		} else if (nOsp == 0 && chiusura) {
			signal (pulizia);
		}
	}

	public void entraLocale () {
		if (nLoc == NMAX || chiusura || (!empty(attesaOspiti) && nLoc == 0)) {
			wait (locali);
		}
		nLoc++;
		if (nLoc < NMAX && !chiusura && !empty (locali)) {
			signal (locali);
		}
	}

	public void esciLocale () {
		nLoc--;

		if (!empty (ospiti) && nLoc == 0 && !chiusura) {
			signal (ospiti);
		} else if (!empty (locali) && empty (ospiti) && !chiusura) {
			signal (locali);
		} else if (nLoc == 0 && chiusura) {
			signal (pulizia);
		}
	}

	public void pulisciBar () {
		chiusura = true;
		if (nLoc > 0 || nOsp > 0) {
 			wait (pulizia);
		}
		<...pulisci...>
		chiusura = false;
		if (!empty(ospiti) {
			signal (ospiti);
		} else if (!empty (locali)) {
			signal (locali);
		}
	}
}

Scambio di messaggi asincrono

Implementazione in scambio di messaggi asincrono del problema "il bar dello stadio". Seguono le implementazioni del processo gestore e le interfacce Barista, Locali, Ospiti.

Gestore

process gestoreBar {
	port signal entraOsp, entraLoc, esciOsp, esciLoc;
	port signal richiestaPulizia, finePulizia;
	process barista, locale, ospite;
	int nLoc = 0;
	int nOsp = 0;
	bool chiusura = false;
	signal s;
	queue attesaOsp, attesaLoc; 	// inizializzate come empty

	// helper function per svegliare in maniera corretta i processi in coda
	public void svegliaProcesso () {

		if (chiusura && nOsp == 0 && nLoc == 0) {
			send (s) to barista.ok_pulizia;
			barista = receive (s) from finePulizia;

		} else if (!chiusura && !attesaOsp.empty && nLoc == 0) {
			while (!attesaOsp.empty && nOsp < NMAX) {
				ospite = attesaOsp.dequeue();
				send (s) to ospite.ok_entra;
				nOsp++;
			}

		} else if (!chiusura && !attesaLoc.empty && nOsp == 0 && attesaOsp.empty) {
			while (!attesaLoc.empty && nLoc < NMAX) {
				locale = attesaLoc.dequeue();
				send (s) to locale.ok_entra;
				nLoc++;
			}
		}
	}

	...
	// implementazione con guardie logiche
	do {
		* (nLoc == 0 && !chiusura && nOsp < NMAX); ospite = receive(s) from entraOsp; ->
			send(s) to ospite.ok_entra;
			nOsp++;

		* (nOsp == 0 && !chiusura && nLoc < NMAX); locale = receive(s) from entraLoc; ->
			send(s) to ospite.ok_entra;
			nLoc++;

		* (chiusura || (nOsp == NMAX && nLoc == 0)); ospite = receive(s) from entraOsp; ->
			attesaOsp.enqueue(ospite)

		* (chiusura || (nLoc == NMAX && nOsp == 0)); locale = receive(s) from entraLoc; ->
			attesaLoc.enqueue(locale)

		* barista = receive(s) from richiestaPulizia; ->
			chiusura = true;
			if (nLoc == 0 && nOsp == 0) {
				send (s) to barista.ok_pulizia;
				// qui pulisce
				barista = receive(s) from finePulizia;
				chiusura = false;

				svegliaProcesso();
			}

		* ospite = receive(s) from esciOsp; ->
			nOsp--;
			svegliaProcesso();

		* locale = receive(s) from esciLoc; ->
			nLoc--;
			svegliaProcesso();
	} od

Barista

process Barista {
	port signal ok_pulizia;
	signal s;
	process p;
	...
	send (s) to gestoreBar.richiestaPulizia;
	p = receive(s) from ok_pulizia;
	<...pulisci...>
	send (s) to gestoreBar.finePulizia;
	...
}

Ospiti

process Ospite {
	port signal ok_entra;
	signal s;
	process p;
	...
	send (s) to gestoreBar.entraOsp;
	p = receive(s) from ok_entra;
	<...bevi birra come un vero tifoso in trasferta...>
 	send (s) to gestoreBar.esciOsp;
	...
}

Locali

process Locale {
	port signal ok_entra;
	signal s;
	process p;
	...
	send (s) to gestoreBar.entraLoc;
	p = receive(s) from ok_entra;
	<...bevi birra come un vero tifoso in casa...>
 	send (s) to gestoreBar.esciLoc;
	...
}

Rendez-vous

process bar {
	entry entraOspite;
	entry ok_entraOspite;
	entry entraLocale;
	entry ok_entraLocale;
	entry esciOspite;
	entry esciLocale;
	entry pulizia;
	entry ok_pulizia;
	entry fine_pulizia;
	int nLoc = 0;
	int nOsp = 0;
	int attesaLoc = 0;
	int attesaOsp = 0;
	bool chiusura = false;

	do {
		* (!chiusura); accept entraOspite {}; ->
			if (nOsp == NMAX) {
				attesaOsp++;
			} else {
				accept ok_entraOspite;
				nOsp++;
			}

		* accept esciOspite {}; ->
			nOsp--;
			if (attesaOsp > 0 && !chiusura) {
				while (attesaOsp > 0 && nOsp < NMAX) {
					accept ok_entraOspite;
				}
			} else if (attesaOsp == 0 && !chiusura && nOsp == 0 && attesaLoc > 0) {
				while (attesaLoc > 0 && nLoc < NMAX) {
					accept ok_entraLocale;
				}
			} else if (chiusura && nOsp == 0) {
				accept ok_pulizia;
			}

		* (!chiusura); accept entraLocale {}; ->
			if (nLoc == NMAX || (attesaOsp > 0 && nLoc == 0)) {
				attesaLoc++;
			} else {
				accept ok_entraLocale;
				nLoc++;
			}

		* accept esciLocale {}; ->
			nLoc--;
			if (nLoc == 0 && attesaOsp > 0 && !chiusura) {
				while (attesaOsp > 0 && nOsp < NMAX) {
					accept ok_entraOspite;
				}
			} else if (attesaLoc > 0 && !chiusura) {
				while (attesaLoc > 0 && nLoc < NMAX) {
					accept ok_entraLocale;
				}
			} else if (chiusura && nLoc == 0) {
				accept ok_pulizia;
			}

		* accept pulizia {}; ->
			chiusura = true;
			if (nLoc == 0 && nOsp == 0) {
				accept ok_pulizia;
			}

		* accept fine_pulizia {}; ->
			chiusura = false;
	} od
}

Ospiti

process ospite {
	...
	call bar.entraOspite;
	call bar.ok_entraOspite;
	... bevi ...
	call bar.esciOspite;
}

Locali

process locale {
	...
	call bar.entraLocale;
	call bar.ok_entraLocale;
	... bevi ...
	call bar.esciLocale;
}

Barista

process barista {
	...
	call bar.pulizia;
	call bar.ok_pulizia;
	... pulisci ...
	call bar.fine_pulizia;
}