Un parcheggio offre 30 posti auto, non tutti uguali:

Le vetture che non possono accedere al parcheggio vengono bloccate all’ingresso. In questo caso, quando queste vetture verranno sbloccate potranno accedere solamente a parcheggi del tipo corrispondente.

Una vettura “S” che arriva all’ingresso può accedere ad un posto “M” solo se non ci sono posti liberi “S” e almeno 3 posti “M” sono occupati da vetture “M”.

Una vettura “S” che arriva all’ingresso può accedere ad un posto “L” solo se non ci sono posti liberi “S” e la vettura non può accedere a posti “M”

Una vettura “M” che arriva all’ingresso può accedere ad un posto “L” solo se non ci sono posti liberi “M” e le vetture “M” già presenti nel parcheggio sono meno di 15.

Programmare l’ingresso e l’uscita delle vetture di ogni tipo usando i semafori con la semantica tradizionale.

//variabili
busyL = busyM = busyS = 0; //numero di posti occupati, sempre tra 0 e 10
inM = 0; //numero di macchine M nel parcheggio (slot M o L)
inMM = 0; //numero di macchine M negli slot M
wL = wM = wS = 0; //numero di macchine in attesa di entrare

//semafori
mutex = 1;
semL = semM = semS = 0; //semafori per bloccare le macchine

boolean canSS(){return busyS < 10;}
boolean canMM(){return busyM < 10;}
boolean canLL(){return busyL < 10;}
boolean canSM(){return (busyM < 10 && inMM >= 3);} //busyS >= 10 non controllata
boolean canSL(){return (busyL < 10 && canSM());} //busyS >= 10 non controllata
boolean canML(){return (busyL < 10 && inM < 15);} //musyM > 0 non controllata

void inSS(){busySS++;}
void inSM(){busyM++;}
void inSL(){busyL++;}
void inMM(){busyM++; inM++; inMM++;}
void inML(){busyL++; inM++;}
void inLL(){busyL++;}

void outS(){
	if(wM > 0){wS--; signal(semS);}
	else{busyS--;}
}

void outM(){
	if(wM > 0){wM--; inM++; inMM++; signal(semM);}
	else{busyM--;}
}

void outL(){
	if(wL > 0){wL--; signal(semL);}
	else{busyL--;}
}

void carS(){
	wait(mutex);
	if(canSS()){busyS++; signal(mutex); park(); wait(mutex); outS(); signal(mutex);}
	else{
		if(canSM()){busyM++; signal(mutex); park(); wait(mutex); outM(); signal(mutex);}
		else{
			if(canSL()){busyL++; signal(mutex); park(); wait(mutex); outL(); signal(mutex);}
			else{
				wS++; signal(mutex); wait(semS); park(); wait(mutex); outS(); signal(mutex);
			}
		}
	}
}

void carM(){
	wait(mutex);
	if(canMM()){
		busyM++; inM++; inMM++; signal(mutex);
		park();
		wait(mutex); inM--; inMM--; outM(); signal(mutex);
	}else{
		if(canML()){
			busyL++; inM++; signal(mutex);
			park();
			wait(mutex); inM--; outL(); signal(mutex);
		}else{
			wM++; signal(mutex); wait(semM); 
			park();
			wait(mutex); outM(); signal(mutex);
		}
	}
}

void carL(){
	wait(mutex);
	if(canLL){
		busyL++; signal(mutex);
		park();
		wait(mutex); outL(); signal(mutex);
	}else{
		wL++; signal(mutex); wait(semL);
		park();
		wait(mutex); outL(); signal(mutex);
	}
}