Prova Teorica 20-01-2015

From Sistemi Operativi
Jump to navigation Jump to search

Es. c.1

Scrivere il monitor lwlrbb. Il monitor deve implementare le seguenti procedure entry:
     - void write(generic_type val);
     - generic_type read(void);

Il lwlrbb si comporta come un bounded buffer di MAX elementi che coordina l'attivita' di numerosi processi produttori/scrittori 
e numerosi lettori/consumatori. lwlrbb ammette un numero massimo (sempre MAX) di lettori e scrittori in attesa.

Se il buffer e' vuoto e ci sono piu' gia' MAX lettori in attesa, il lettore che e' in attesa da piu' tempo esce resituendo NULL.

In ugual modo se il buffer e' completamente pieno e ci sono gia' MAX scrittori che attendono di scrivere viene perduto il valore che da
piu' tempo nel buffer attende di venir letto, il primo processo in attesa di scrivere puo' cosi' scrivere il suo elemento nel buffer e sbloccarsi.

Soluzione di BAGG

#define MAX 42

monitor lwlrbb {
    generic_type bb[] ;
    int count, front, rear ; 	/* rispettivamente: numero elementi, dove scrivere nel buffer, dove leggere nel buffer */
    int nw, nr ; 		/* rispettivamente numero di writer e reader */
    bool exit ; 		/* server ai reader per sapere se devono ritornare NULL al loro rientro nel monitor  */
    condition canr, canw ;

    lwlrbb(void) {
        bb = new generic_type[MAX] ;
        count = front = rear = nw = nr = exit = 0 ;
    }

    entry void write(generic_type val) {
        if(count == MAX) {			/* se count è MAX non si può scrivere  */
            if(nw == MAX) {			/* se la coda è piena devo fare spazio */	
                rear = (rear + 1)%MAX ;         /* rear indica il più vecchio elemento ancora da leggere, lo incremento --> salto l'elemento */
                count -= 1 ;
                nw += 1 ;			/* incremento prima perchè anche se la coda è piena ora dopo la signal ci sarà un posto...  */
                canw.signal() ;			/* ora il primo che aspettava può scrivere --> lo sveglio  */
                canw.wait() ;
                nw -= 1 ;
            } else {				/* se la coda non è piena devo comunque aspettare...  */
                nw += 1 ;
                canw.wait() ;
                nw -=1 ;
            }
        } 
	bb[front] = val ;					
        front = (front + 1)%MAX ;
        count += 1 ;
        canr.signal() ;				/* potrebbe esserci un reader che aspetta --> segnalo che ho scritto e si può leggere  */
    }

    entry generic_type read(void) {
        if(count == 0) {			/* se non c'è nulla da leggere allora devo aspettare  */
            if(nr == MAX) {			/* se la coda è piena setto exit, che i reader controllano per sapere se sono stati svegliati per ritornare NULL  */
                exit = 1 ;
                canr.signal() ;		        /* sveglio il condannato...  */
            } nr += 1 ;				/* mi accodo... */
            canr.wait() ;
            nr -= 1 ;
            if(exit) {				/* se sono il condannato resetto la variabile ed esco...  */
                 exit = 0 ;
                 return NULL ;
            }
        }
        generic_type r = bb[rear] ;
        rear = (rear + 1)%MAX ;
        count -= 1 ;
        canw.signal() ;				/* ho letto, quindi si è liberato un posto e almeno un writer può scrivere... */
        return r ;
    }
}