ProvaTeorica 2013.07.19

From Sistemi Operativi
Jump to navigation Jump to search

Esecizio C1: scrivere un monitor m vie che gestisca M buffer limitati. Ogni buffer ha l'ampiezza di M ELEM elementi. I produttori chiamano la procedure entry: put(generic *object) mentre i consumatori chiamano la procedure entry generic *get(int n) I produttori conferiscono un vettore di M element i, uno per ogni buffer al buffer. Per esempio put( v ), (dove v e' un vettore di M elementi) inserisce ogni elemento del vettore nel buffer corrispondente. I consumatori ricevono un oggetto dal buffer indicato come parametro oggetti ma attendono sempre che ci sia almeno un elemento in ogni buffer.

Mia Soluzione:

/*AreEmpy: */
/*true quando almeno un buff é vuoto*/
/*false quando tutti hanno almeno un elemento*/
bool areEmpy(*buff){
	for(int a = 0; a<M;a++){
		if(buff[a].lengh != 0){
			return true;
		}
        }
	return false;
}
/*AreFull: */
/*true quando almeno un buff é pieno*/
/*false quando sono tutti non pieni*/
bool areFull(*buff){
	for(int a =  0; a<M;a++){
		if (buff[a].lengh == MELEM){
			return true;
		}
	}

	return false;   
}
monitor mvie{
	put(generic *object){
		if( areFull(buff) ) 
			oktoput.wait();
		for(int a = 0; a<M;a++){
			buf[a].queue(object[a]);
		}
		for(int a = 0; a<M;a++){
			oktoget[a].signal();//tutti i buffer hanno almeno un elemento quindi manda la signal a tutti i lettori
		}
	}

	generic *get(int i){
		if( areEmpty(buff))
			oktoget.wait();
		buf[i].dequeue(); 
		if(!areFull(buf)) //  se cé spazio in tutti i buffer manda la signal per scrivere
			oktoput.signal(); 
    	}

}

- Midolo


Questa è la mia soluzione:

int everything_set(queue[]) /*prende un array di code e ritorna 1 se sono tutte non vuote*/
int not_full(queue[]) /*prende un array di code e ritorna 1 se tutte le code hanno meno di MELEM elementi*/

monitor mvie
{
	queue buf[M];
	condition oktowrite,oktoread;
	procedure entry put(generic *object)
	{
		if (!not_full(buf))
			oktowrite.wait();
		for (i=0;i<M;i++)
		{
			buf[i].enqueue(object[i]);
		}
		oktoread.signal();
	}
	procedure entry generic* get (int n)
	{
		if (!everything_set(buf))
			oktoread.wait();
		generic g=buf[n].dequeue();
		if (not_full(buf)
			oktowrite.signal();
	}
}

-stefano92


Secondo me, bloccare il processo che vuole fare PUT, nel caso in cui esiste un buffer pieno, determina DEADLOCK.

Infatti il testo non lo chiede. Faccio un esempio:

Buffer 1: (empty)

Buffer 2: (full)

Processo 1: GET -> si blocca in quanto il Buffer 1 e' vuoto.

Processo 2: PUT -> si blocca in quanto il Buffer 2 e' pieno.

...etc...

DEADLOCK


Quando aggiungi a tutti e togli a 1 solo, e' plausibile che si formi, prima o poi, la situazione descritta sopra: un buffer pieno e uno vuoto. Nella mia soluzione quindi non c'e' questo controllo.

monitor mvie
{
	condition okP, okG;
	queue buf[M];
	
	bool isOneEmpty()
	{
		for (int i = 0; i < M; i++)
			if (buf[i].isEmpty())
				return true;
				
		return false;
	}
	
	procedure entry put(generic *object)
	{
		for (int i = 0; i < M; i++)
			if (buf[i].length() < MELEM)
				buf[i].enqueue(object[i]);
		
		okG.signal();
	}
	
	procedure entry generic *get(int n)
	{
		if (isOneEmpty())
			okG.wait();
		
		return buf[n].dequeue();
	}
}

-TomOgn

uhm...per l'idea di buffer come l'abbiamo sempre visto mi sembra strano che una put su un buffer pieno vada "buttata"... d'altronde anche quello che dici tu è vero, ponendo attesa in caso di buffer pieno si provoca indubbiamente deadlock XD



monitor mvie{
	queue buffer[M];
	condition oktoput;
	condition oktoget;
	
	mvie(){
		int i;
		for(i=0; i<M; i++)
			buffer[i] = new queue(MELEM);
		}
		
	put(generic *object){
		int i;
		boolean b=1;
		for(i=0; i<M; i++){
			if(!(buffer[i].len < MELEM))
				b=0;
			}
		if(b == 0) /*almeno un elemento non era disponibile*/
			oktoput.wait();
		
		for(i=0; i<M; i++)
			buffer[i].enqueue(object[i]);
		oktoget.signal();
		}
		
	generic *get(int n){
		int i;
		boolean b=1;
		for(i=0; i<M; i++){
			if(buffer[i].len == 0)
				b=0;
			}
		if(b == 0)
			oktoget.wait();
		
		object toread = buffer[n].dequeue;
		/* dobbiamo controllare che ci sia almeno un elemento libero per ciascun buffer prima di fare la signal */
		b = 1;
		for(i=0; i<M; i++){
			if(!(buffer[i].len < MELEM))
				b=0;
			}
		if(b)
			oktoput.signal();
		}
	}

Gabriele e Giulia

monitor mvie
{
	condition oktoread;
	queue buffer[M];
	
	bool control1empty()
	{
		for (int i = 0; i < M; i++)
			if (buffer[i].length==0)
				return true;
				
		return false;
	}



	procedure entry put(generic *object)
	{
		for (int i = 0; i < M; i++)
		{         
                           if (buffer[i].length < MELEM)
				buffer[i].enqueue(object[i]);
                           
		}
		oktoread.signal();
		
	}
	
	procedure entry generic *get(int n)
	{
	
			 if (control1empty())      # se trova un buffer vuoto, wait.
			       oktoread.wait();

		       return buffer[n].dequeue();  # consuma l'oggetto n
	}
}

Save