Difference between revisions of "ProvaTeorica 2013.07.19"
(Created page with "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 *obj...") |
|||
(8 intermediate revisions by 5 users not shown) | |||
Line 23: | Line 23: | ||
/*AreFull: */ | /*AreFull: */ | ||
/*true quando almeno un buff é pieno*/ | /*true quando almeno un buff é pieno*/ | ||
− | /*false quando sono tutti pieni*/ | + | /*false quando sono tutti non pieni*/ |
bool areFull(*buff){ | bool areFull(*buff){ | ||
for(int a = 0; a<M;a++){ | for(int a = 0; a<M;a++){ | ||
Line 56: | Line 56: | ||
</syntaxhighlight> | </syntaxhighlight> | ||
- Midolo | - Midolo | ||
+ | |||
+ | |||
+ | Questa è la mia soluzione: | ||
+ | |||
+ | <syntaxhighlight lang="C"> | ||
+ | |||
+ | 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(); | ||
+ | } | ||
+ | } | ||
+ | |||
+ | </syntaxhighlight> | ||
+ | -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. | ||
+ | |||
+ | <syntaxhighlight lang="C"> | ||
+ | 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(); | ||
+ | } | ||
+ | } | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | -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 | ||
+ | |||
+ | |||
+ | ---- | ||
+ | |||
+ | <syntaxhighlight lang="C"> | ||
+ | |||
+ | 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(); | ||
+ | } | ||
+ | } | ||
+ | </syntaxhighlight> | ||
+ | Gabriele e Giulia | ||
+ | <syntaxhighlight lang="C"> | ||
+ | |||
+ | |||
+ | 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 | ||
+ | |||
+ | </syntaxhighlight> |
Latest revision as of 16:40, 28 May 2014
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