<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://so.v2.cs.unibo.it/wiki/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Barba</id>
	<title>Sistemi Operativi - User contributions [en]</title>
	<link rel="self" type="application/atom+xml" href="https://so.v2.cs.unibo.it/wiki/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Barba"/>
	<link rel="alternate" type="text/html" href="https://so.v2.cs.unibo.it/wiki/index.php/Special:Contributions/Barba"/>
	<updated>2026-04-30T16:46:56Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.35.5</generator>
	<entry>
		<id>https://so.v2.cs.unibo.it/wiki/index.php?title=Prove_scritte_2022&amp;diff=3067</id>
		<title>Prove scritte 2022</title>
		<link rel="alternate" type="text/html" href="https://so.v2.cs.unibo.it/wiki/index.php?title=Prove_scritte_2022&amp;diff=3067"/>
		<updated>2024-01-21T09:55:52Z</updated>

		<summary type="html">&lt;p&gt;Barba: /* Proposta di soluzione 1 (da controllare) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Prova 2022/09/06 =&lt;br /&gt;
&lt;br /&gt;
== Esercizio c1 == &lt;br /&gt;
&lt;br /&gt;
Esercizio c.1: I bit di un numero intero rappresentano condizioni di un sistema. Se lo stato attuale è 6 (0110) vuole dire&lt;br /&gt;
che attualmente sono vere le condizioni 2 (0010) e 4 (0100).&lt;br /&gt;
Scrivere un monitor bitcond che fornisca le seguenti procedure entry:&lt;br /&gt;
void set(int bit2set); accende nello stato attuale i bit di bit2set&lt;br /&gt;
void unset(int bit2unset) spegne nello stato attuale i bit di bit2unset&lt;br /&gt;
void statuswait(int bit2wait) attende che lo stato attuale soddisfi tutti le condizioni indicate in bit2wait (cioè&lt;br /&gt;
che tutti i bit in bit2wait siano accesi nello stato attuale).&lt;br /&gt;
Le richieste statuswait devono essere servite in ordine FIFO (cioè un processo anche se sono presenti tutte le&lt;br /&gt;
condizioni necessarie deve attendere se un processo che ha chiamato statuswait prima è in attesa).&lt;br /&gt;
Lo stato iniziale è zero (nessuna risorsa disponibile)&lt;br /&gt;
&lt;br /&gt;
=== Soluzione proposta 1 ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
class bitcond{&lt;br /&gt;
  int bitmap;&lt;br /&gt;
  int lastBitmask;&lt;br /&gt;
  int has=0;&lt;br /&gt;
  &lt;br /&gt;
  condition waiting;&lt;br /&gt;
  condition c;&lt;br /&gt;
&lt;br /&gt;
  void set(int i){&lt;br /&gt;
    bitmap|=i; &lt;br /&gt;
      if(bitmap&amp;amp;lastBitmask == bitmap) c.signal();&lt;br /&gt;
  }&lt;br /&gt;
  void unset(int i){&lt;br /&gt;
    bitmap&amp;amp;=~i; &lt;br /&gt;
  }&lt;br /&gt;
  void statuswait(int i){&lt;br /&gt;
    has++; &lt;br /&gt;
    if(has&amp;gt;1){&lt;br /&gt;
      waiting.wait();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if(!(bitmap&amp;amp;i==i)){&lt;br /&gt;
      lastBitmask=i;&lt;br /&gt;
      c.wait();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    waiting.signal();&lt;br /&gt;
    has--;&lt;br /&gt;
  }&lt;br /&gt;
  bitcond(){&lt;br /&gt;
    bitmap = 0;&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Soluzione proposta 2 ===&lt;br /&gt;
Proposta da [[User:Flecart|Flecart]] ([[User talk:Flecart|talk]]) 12:06, 14 January 2023 (CET)&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
&lt;br /&gt;
const int int_size = 32;&lt;br /&gt;
&lt;br /&gt;
class monitor {&lt;br /&gt;
    int value;&lt;br /&gt;
    condition bitset[int_size];&lt;br /&gt;
&lt;br /&gt;
    int numstatuswaiting;&lt;br /&gt;
    condition waiting;&lt;br /&gt;
    &lt;br /&gt;
    monitor() {&lt;br /&gt;
        value = 0;&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    /// guarda se il bit n-significativo è settato in from&lt;br /&gt;
    bool nbit(int from, int n) {&lt;br /&gt;
        return (from &amp;amp; (1 &amp;lt;&amp;lt; n)) != 0&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    void entry set(int bit2set) {&lt;br /&gt;
        value |= bit2set;&lt;br /&gt;
&lt;br /&gt;
        for (int i = 0; i &amp;lt; 32; i++) {&lt;br /&gt;
            if (nbit(value, i))&lt;br /&gt;
                bitset[i].signal();&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    void entry statuswait(int bit2wait) {&lt;br /&gt;
        // in questo modo solamente un singolo processo è dentro ad aspettare&lt;br /&gt;
        // che tutte le condizioni siano rispettate&lt;br /&gt;
        if (numstatuswaiting &amp;gt; 0)&lt;br /&gt;
            waiting.wait();&lt;br /&gt;
        &lt;br /&gt;
        numstatuswaiting++;&lt;br /&gt;
        int i = 0;&lt;br /&gt;
        while(i &amp;lt; 32) {&lt;br /&gt;
            if (nbit(bit2wait, i) &amp;amp;&amp;amp; !nbit(value, i)) {&lt;br /&gt;
                bitset[i].wait();&lt;br /&gt;
&lt;br /&gt;
                // ricomincia a guardare tutti i bit da zero, perché&lt;br /&gt;
                // nel frattempo potrebbero essere cambiati.&lt;br /&gt;
                // -1 così con l'istruzione successiva diventa 0&lt;br /&gt;
                i = -1; &lt;br /&gt;
            }&lt;br /&gt;
            i++;&lt;br /&gt;
        }&lt;br /&gt;
        &lt;br /&gt;
        numstatuswaiting--;&lt;br /&gt;
        waiting.signal();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Soluzione proposta 3 ===&lt;br /&gt;
Proposta da [[User:Flecart|Flecart]] ([[User talk:Flecart|talk]]) 12:07, 14 January 2023 (CET)&lt;br /&gt;
questa è la soluzione più brutta, ma dovrebbe andare.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
&lt;br /&gt;
const int int_size = 32;&lt;br /&gt;
&lt;br /&gt;
class monitor {&lt;br /&gt;
    int value;&lt;br /&gt;
    condition status;&lt;br /&gt;
&lt;br /&gt;
    int numstatuswaiting;&lt;br /&gt;
    condition waiting;&lt;br /&gt;
    &lt;br /&gt;
    monitor() {&lt;br /&gt;
        value = 0;&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    /// guarda se il bit n-significativo è settato in from&lt;br /&gt;
    bool nbit(int from, int n) {&lt;br /&gt;
        return (from &amp;amp; (1 &amp;lt;&amp;lt; n)) != 0&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    void entry set(int bit2set) {&lt;br /&gt;
        value |= bit2set;&lt;br /&gt;
        status.signal();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
    void entry unset(int bit2unset) {&lt;br /&gt;
        value = (value &amp;amp; ~bit2unset);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    void entry statuswait(int bit2wait) {&lt;br /&gt;
        // in questo modo solamente un singolo processo è dentro ad aspettare&lt;br /&gt;
        // che tutte le condizioni siano rispettate&lt;br /&gt;
        if (numstatuswaiting &amp;gt; 0)&lt;br /&gt;
            waiting.wait();&lt;br /&gt;
        &lt;br /&gt;
        numstatuswaiting++;&lt;br /&gt;
        while(true) {&lt;br /&gt;
            if ((value &amp;amp; bit2wait) == bit2wait) &lt;br /&gt;
                break;&lt;br /&gt;
            else &lt;br /&gt;
                status.wait();&lt;br /&gt;
        }&lt;br /&gt;
        numstatuswaiting--;&lt;br /&gt;
        waiting.signal();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Esercizio c2 ==&lt;br /&gt;
&lt;br /&gt;
[[ 20220906c2 ]]  proposte di soluzione&lt;br /&gt;
&lt;br /&gt;
= Prova 2022/07/20 =&lt;br /&gt;
&lt;br /&gt;
== Esercizio c1 == &lt;br /&gt;
&lt;br /&gt;
in un porto con una sola banchina utilizzabile occorre caricare cereali sulle navi. I camion portano i cereali al porto. Una sola nave alla volta può essere attraccata al molo, un solo camion alla volta scarica i cereali nella nave.&lt;br /&gt;
Il codice eseguito da ogni nave è:&lt;br /&gt;
   nave[i] process:&lt;br /&gt;
     porto.attracca(capacità) &lt;br /&gt;
     porto.salpa()&lt;br /&gt;
     ...naviga verso la destinazione&lt;br /&gt;
&lt;br /&gt;
Il codice di ogni camion è:&lt;br /&gt;
  camion[j] process: &lt;br /&gt;
    while (1):&lt;br /&gt;
      quantità = carica_cereali()&lt;br /&gt;
      porto.scarica(quantità)&lt;br /&gt;
&lt;br /&gt;
I camion fanno la spola dai depositi alla nave. La nave arriva vuota e può salpare solo se è stata completamente riempita (la somma delle quantità scaricate dai camion raggiunge la capacità indicata come parametro della funzione attracca). Se un camion può scaricare solo parzialmente il suo carico rimane in porto e aspetta di completare l'operazione con la prossima nave che attraccherà al molo.&lt;br /&gt;
Scrivere il monitor porto.&lt;br /&gt;
&lt;br /&gt;
=== Soluzione proposta 1 (da controllare) ===&lt;br /&gt;
Proposta da [[User: SpookyWiki |SpookyWiki]] ([[User talk:SpookyWiki|talk]]) 14:56, 13 May 2023 (CEST)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
&lt;br /&gt;
// in questa versione, se il remainingSpace è -1 vuol dire che nessuna &lt;br /&gt;
	//barca è attraccata&lt;br /&gt;
monitor porto{&lt;br /&gt;
&lt;br /&gt;
	int remainingSpace; // -1 -&amp;gt; non ci sono barche attraccate&lt;br /&gt;
	bool camionSlotBusy;&lt;br /&gt;
	condition waiting4slot; //il camion attende di essere preso in carico&lt;br /&gt;
	condition waiting4dock; //la barca attende il molo&lt;br /&gt;
	condition waiting4load; //il la barca attende i camion&lt;br /&gt;
	condition waiting4boat; //i camion attendono una barca&lt;br /&gt;
&lt;br /&gt;
	porto {&lt;br /&gt;
		remainingSpace = -1;&lt;br /&gt;
		camionSlotBusy = false;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	procedure entry void attracca(int capacità){&lt;br /&gt;
		if( remainingSpace &amp;gt;=0 )&lt;br /&gt;
			wait4dock.wait();&lt;br /&gt;
		remainingSpace = capacità;&lt;br /&gt;
		waiting4slot.signal();&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	procedure entry void salpa(){&lt;br /&gt;
		if( remainingSpace &amp;gt; 0 )&lt;br /&gt;
			wait4load.wait();&lt;br /&gt;
		waiting4dock.signal();&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	procedure entry void scarica(quantità){&lt;br /&gt;
		if( camionSlotBusy ) &lt;br /&gt;
			waiting4slot.wait()&lt;br /&gt;
		//se non posso scaricare il carico&lt;br /&gt;
		if( remainingSpace &amp;lt;= 0)&lt;br /&gt;
			waiting4boat.wait()&lt;br /&gt;
&lt;br /&gt;
		int remainingLoad = quantità;&lt;br /&gt;
&lt;br /&gt;
		while (remainingLoad &amp;gt; 0){&lt;br /&gt;
			//il camion si svuota e se ne deve andare&lt;br /&gt;
			if( remainingSpace &amp;gt;= remainingLoad ) {&lt;br /&gt;
				remainingSpace -= remainingLoad;&lt;br /&gt;
				remainingLoad = 0;&lt;br /&gt;
				if ( remainingSpace == 0)&lt;br /&gt;
					wait4load.signal();&lt;br /&gt;
			//il camion non si svuota del tutto e deve rimanere&lt;br /&gt;
			} else {&lt;br /&gt;
				remainingLoad -= remainingSpace;&lt;br /&gt;
				remainingSpace = 0;&lt;br /&gt;
				waiting4load.signal();&lt;br /&gt;
				waiting4boat.wait();&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
		waiting4slot.singal();&lt;br /&gt;
		&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Prova 2022/06/21 =&lt;br /&gt;
&lt;br /&gt;
== Esercizio c1 ==&lt;br /&gt;
Scrivere il monitor collocamento:&lt;br /&gt;
  void cercolavoro(char *nome, char *skill)&lt;br /&gt;
  void char *assumo(char * skill)&lt;br /&gt;
Quando un processo chiama la cercolavoro si mette in attesa di una richiesta di lavoro e rimane bloccato nel monitor&lt;br /&gt;
fino a che non è stato assunto. Nella cercolavoro viene indicato il nome dell'aspirante lavoratore la sua capacità (skill).&lt;br /&gt;
Un datore di lavoro con necessità di personale chiama la assumo specificando la capacità richiesta. Se c'è in attesa&lt;br /&gt;
almeno un aspirante lavoratore con quella specifica capacità (uguale valore di skill), il datore di lavoro riceve il nome del&lt;br /&gt;
nuovo dipendente ed entrambi i processi escono dal monitor. Nel caso non ci siano richieste compatibili il datore di&lt;br /&gt;
lavoro si blocca nel monitor attendendo un lavoratore con la capacità cercata. Quando arriva il lavoratore che soddisfa&lt;br /&gt;
le richieste si sbloccano entrambi i processi lavoratore e datore di lavoro. La assumo restituisce in ogni caso il nome del&lt;br /&gt;
dipendente da assumere.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Soluzione proposta === &lt;br /&gt;
&lt;br /&gt;
Soluzione proposta da [[User:Flecart|Flecart]] ([[User talk:Flecart|talk]]) 12:08, 14 January 2023 (CET)&lt;br /&gt;
&lt;br /&gt;
ci potrebbe essere un errore in quanto non è specificato il comportamento della struttura dati in alcune situazioni&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
&lt;br /&gt;
class collocamento{&lt;br /&gt;
&lt;br /&gt;
set&amp;lt;char *, condition&amp;gt; richieste;  // chi assume cerca questa skill&lt;br /&gt;
set&amp;lt;char *, char *, condition&amp;gt; ricerche; // nome e skill di chi cerca&lt;br /&gt;
&lt;br /&gt;
char *last_nome;&lt;br /&gt;
&lt;br /&gt;
collocamento {&lt;br /&gt;
	last_nome = NULL;&lt;br /&gt;
	richieste = set();&lt;br /&gt;
	ricerche = set();	&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void cercolavoro(char *nome, char *skill) {&lt;br /&gt;
	datore = richieste.find(skill);  // cerca valutando la prima come chiave&lt;br /&gt;
	if (datore != NULL) {&lt;br /&gt;
		&amp;lt;skill, cond&amp;gt; = datore;&lt;br /&gt;
		richieste.remove(datore);&lt;br /&gt;
		last_nome = nome;&lt;br /&gt;
		cond.signal();		&lt;br /&gt;
	} else {&lt;br /&gt;
		condition c = new condition();&lt;br /&gt;
		ricerche.insert(nome, skill, c);&lt;br /&gt;
		c.wait();&lt;br /&gt;
		free(c);&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void char *assumo(char * skill){&lt;br /&gt;
	lavoratore = ricerche.find2(skill); // cerca valutando la seconda come chiave.&lt;br /&gt;
	if (lavoratore != NULL) {&lt;br /&gt;
		&amp;lt;nome, skill, cond&amp;gt; = lavoratore;&lt;br /&gt;
		ricerche.remove(lavoratore);&lt;br /&gt;
		cond.signal();&lt;br /&gt;
		last_nome = nome;&lt;br /&gt;
	} else {&lt;br /&gt;
		condition c = new condition();&lt;br /&gt;
		richieste.insert(skill, c);&lt;br /&gt;
		c.wait();&lt;br /&gt;
		free(c);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	return last_nome;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
}// class collocamento&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Soluzione proposta === &lt;br /&gt;
&lt;br /&gt;
Soluzione proposta da [[User:Flecart|Flecart Frend]], regalo la proprietà intellettuale di questa soluzione a flecart.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
class workdisptcher{&lt;br /&gt;
&lt;br /&gt;
  // la multi map può storare più di un valore per una chiave&lt;br /&gt;
  // quando viene richiesta una particolare chiave da in maniera LIFO&lt;br /&gt;
  // il risultato&lt;br /&gt;
  // es:&lt;br /&gt;
  // multi_map&amp;lt;char *,int&amp;gt; lavoratori;&lt;br /&gt;
  // lavoratori.insert(&amp;quot;prova&amp;quot;,2);&lt;br /&gt;
  // lavoratori.insert(&amp;quot;prova&amp;quot;,1);&lt;br /&gt;
  // lavoratori.get(&amp;quot;prova&amp;quot;) == 2&lt;br /&gt;
  // lavoratori.remove(&amp;quot;prova&amp;quot;)&lt;br /&gt;
  // lavoratori.get(&amp;quot;prova&amp;quot;) == 1&lt;br /&gt;
  multi_map&amp;lt;char *,(char*,cond)&amp;gt; lavoratori;&lt;br /&gt;
  multi_map&amp;lt;char *,cond&amp;gt; posti_aperti;&lt;br /&gt;
  char* buffer_name;&lt;br /&gt;
  void cercolavoro(char *nome, char *skill){&lt;br /&gt;
    if(posti_aperti.find(skill)){&lt;br /&gt;
      auto entry =posti_aperti.get(skill);&lt;br /&gt;
      posti_aperti.remove(entry);&lt;br /&gt;
      buffer_name=name;&lt;br /&gt;
      entry.1.signal();&lt;br /&gt;
    }else{&lt;br /&gt;
      cond c= new cond();&lt;br /&gt;
      lavoratori.insert(skill,(nome,c)) ;&lt;br /&gt;
      c.wait();&lt;br /&gt;
      free(c);&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
  void char *assumo(char * skill){&lt;br /&gt;
    if(lavoratori.find(skill)){&lt;br /&gt;
      auto entry =lavoratori.get(skill);&lt;br /&gt;
      posti_aperti.remove(entry);&lt;br /&gt;
      auto [nome,cnd] = entry.1;&lt;br /&gt;
      cond.signal();&lt;br /&gt;
      return nome;&lt;br /&gt;
    }else{&lt;br /&gt;
      cond c= new cond();&lt;br /&gt;
      posti_aperti.insert(skill,c) ;&lt;br /&gt;
      c.wait();&lt;br /&gt;
      free(c);&lt;br /&gt;
      return buffer_name;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Esercizio c2 ==&lt;br /&gt;
Un servizio viene fornito in modalità client-server usando message passing asincrono.&lt;br /&gt;
Al fine di aumentare l'efficienza si decide di usare molti server e un processo dispatcher in grado di distribuire le&lt;br /&gt;
richieste agli N server. Quando un processo server è libero riceve dal dispatcher la prossima richiesta da elaborare:&lt;br /&gt;
codice di ogni client (tanti!): .....&lt;br /&gt;
  asend(&amp;lt;getpid(), request&amp;gt;, dispatcher)&lt;br /&gt;
  result = arecv(dispatcher)&lt;br /&gt;
&lt;br /&gt;
server process[i], i = 0, ..., N-1:&lt;br /&gt;
 request = arecv(dispatcher)&lt;br /&gt;
 result = compute(request)&lt;br /&gt;
 asend(&amp;lt;getpid(), result&amp;gt;, dispatcher)&lt;br /&gt;
Scrivere il processo dispatcher. (il dispatcher conosce i pid di tutti i server).&lt;br /&gt;
&lt;br /&gt;
=== Soluzione proposta (sbagliata) === &lt;br /&gt;
&lt;br /&gt;
Soluzione proposta da [https://so.v2.cs.unibo.it/wiki/index.php/User:Flecart Flecart] &lt;br /&gt;
&lt;br /&gt;
Questo esercizio è stato corretto tempo fa in classe dal professore, **non è completamente corretto** se si vuole provare a correggerlo alla fine dell'esercizio c'è scritto cos'è sbagliato.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
&lt;br /&gt;
extern int N;&lt;br /&gt;
process dispatcher() {&lt;br /&gt;
    // indice che tiene conto a quale server dover mandare&lt;br /&gt;
    // per semplicità supponiamo che i server abbiano PID&lt;br /&gt;
    // da 0 a N - 1&lt;br /&gt;
    int i = 0; &lt;br /&gt;
&lt;br /&gt;
    // mappa server a pid del processo che lo ha richiesto.&lt;br /&gt;
    // chiave: pid del server&lt;br /&gt;
    // value: queue richiesta dispatchata al server in chiave&lt;br /&gt;
    map&amp;lt;int, queue&amp;lt;int&amp;gt;&amp;gt; mapper; &lt;br /&gt;
    while (true) {&lt;br /&gt;
        res = arecv(ANY);&lt;br /&gt;
        &lt;br /&gt;
        // in questa parte l'importante è sapere&lt;br /&gt;
        // se la richiesta proviene dal  server o da un altro&lt;br /&gt;
        // processo, ho assunto che la disambiguazione &lt;br /&gt;
        // fosse immediata, un altro modo per checkare questo&lt;br /&gt;
        // è vedere se il PID del messaggio rientri fra quelli&lt;br /&gt;
        // noti al dispatcher.&lt;br /&gt;
        if (&amp;lt;pid, request&amp;gt; = res) {&lt;br /&gt;
            mapper[i].enqueue(pid);&lt;br /&gt;
            asend(request, i /*il i-esimo server*/);&lt;br /&gt;
            i++;&lt;br /&gt;
            i %= N;&lt;br /&gt;
        } else if (&amp;lt;pid, response&amp;gt; = res) {&lt;br /&gt;
            requester_pid = mapper[pid].dequeue();&lt;br /&gt;
            asend(response, requester_pid);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
l'es è sbagliato perchè dovrei mandare ai server liberi, non a round-robin [[User:Flecart|Flecart]] ([[User talk:Flecart|talk]]) 15:52, 14 January 2023 (CET)&lt;br /&gt;
&lt;br /&gt;
=== Soluzione proposta 2 === &lt;br /&gt;
&lt;br /&gt;
Soluzione proposta da [https://so.v2.cs.unibo.it/wiki/index.php/User:Gio Giovanni Spadaccini] &lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
dispatcher{&lt;br /&gt;
  queue&amp;lt;&amp;lt;pid,request&amp;gt;&amp;gt; work;&lt;br /&gt;
  queue&amp;lt;pid&amp;gt; freeserver;&lt;br /&gt;
  map&amp;lt;pid,pid&amp;gt; map_server_to_client;&lt;br /&gt;
  while(true){&lt;br /&gt;
    &amp;lt;pid,message&amp;gt;=arecv(ANY);&lt;br /&gt;
    if pid in servers{&lt;br /&gt;
      client=map_server_to_client.get(pid);&lt;br /&gt;
      map_client_to_server.remove(pid);&lt;br /&gt;
      freeserver.push(pid);&lt;br /&gt;
      asend(&amp;lt;message&amp;gt;,client);&lt;br /&gt;
    }else{&lt;br /&gt;
      work.push(&amp;lt;pid,message&amp;gt;);&lt;br /&gt;
    }&lt;br /&gt;
    while !freeserver.empty() and !work.emtpy(){&lt;br /&gt;
      server_pid = freeserver.pop();&lt;br /&gt;
      &amp;lt;client,msg&amp;gt; = work.pop();&lt;br /&gt;
      map_server_to_client.insert(server,client);&lt;br /&gt;
      asend(msg,server_pid);&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Prova 2022/06/01 =&lt;br /&gt;
&lt;br /&gt;
== Esercizio c1 ==&lt;br /&gt;
&lt;br /&gt;
Scrivere il monitor delay che fornisce due procedure entry:&lt;br /&gt;
  int wait_tick(int nticks)&lt;br /&gt;
  void tick(void)&lt;br /&gt;
La procedure entry tick è pensata per essere richiamata periodicamente (es. ogni secondo o ora o giorno) da un&lt;br /&gt;
processo.&lt;br /&gt;
Quando un processo chiama la wait_tick deve attendere un numero di chiamate della tick pari al parametro nticks.&lt;br /&gt;
Per esempio se un processo chiama wait_tick(2) deve fermarsi e verrà riattivato alla seconda successiva chiamata di&lt;br /&gt;
tick.&lt;br /&gt;
La funzione wait_tick ha come valore di ritorno il numero di processi che erano bloccati al momento della tick che ha&lt;br /&gt;
sbloccato il chiamante.&lt;br /&gt;
Esempio: P chiama wait_tick(2) e si blocca. Q chiama wait_tick(3) e si blocca. T chiama tick() non succede nulla. R&lt;br /&gt;
chiama wait_tick(2) e si blocca. T chiama tick(), viene sbloccata la wait_tick di P e il valore ritornato è 3. T chiama&lt;br /&gt;
tick(), vengono sbloccate le wait_tick di Q e R e il valore ritornato per entrambi i processi è 2&lt;br /&gt;
&lt;br /&gt;
=== Soluzione proprosta 1 (da controllare) ===&lt;br /&gt;
Soluzione proposta da [https://so.v2.cs.unibo.it/wiki/index.php/User:Flecart Flecart] &lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
&lt;br /&gt;
class MonitorDelay {&lt;br /&gt;
    int curr_time;&lt;br /&gt;
    int waiting_num;&lt;br /&gt;
&lt;br /&gt;
    // min heap con il tempo di sblocco dei processi e la condizione su cui è fermato&lt;br /&gt;
    // il tempo di sblocco minore è messo in cima alla heap&lt;br /&gt;
    // la sintassi con pair è ispirata alla std::pair di c++&lt;br /&gt;
    heap&amp;lt;pair&amp;lt;int, condition&amp;gt;&amp;gt; waiting; &lt;br /&gt;
&lt;br /&gt;
    void init() {&lt;br /&gt;
        curr_time = 0;&lt;br /&gt;
        waiting = heap&amp;lt;pair&amp;lt;int, condition&amp;gt;&amp;gt;();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    int entry wait_tick(int nticks) {&lt;br /&gt;
        if (nticks &amp;lt;= 0) {&lt;br /&gt;
            return waiting.size();&lt;br /&gt;
        } else {&lt;br /&gt;
            condition c = new condition();&lt;br /&gt;
            waiting.insert(make_pair(nticks + curr_time, c));&lt;br /&gt;
            c.wait();&lt;br /&gt;
            free(c);&lt;br /&gt;
        }&lt;br /&gt;
        return waiting_num;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
    void entry tick(void) {&lt;br /&gt;
        waiting_num = waiting.size();&lt;br /&gt;
        curr_time++;&lt;br /&gt;
&lt;br /&gt;
        while (waiting.head().first &amp;lt;= curr_time) {&lt;br /&gt;
            condition c = waiting.head().second;&lt;br /&gt;
            waiting.deleteHead();&lt;br /&gt;
            c.signal();&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Soluzione proposta 2 (da controllare) ===&lt;br /&gt;
Proposta da [[User: SpookyWiki |SpookyWiki]] ([[User talk:SpookyWiki|talk]]) 18:06, 22 May 2023 (CEST)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
monitor delay {&lt;br /&gt;
	Map&amp;lt;pid_t, int tickleft&amp;gt; tickmap;&lt;br /&gt;
	pid_t last;&lt;br /&gt;
	int blocked;&lt;br /&gt;
	int quit;&lt;br /&gt;
	condition wait4ticks;&lt;br /&gt;
	&lt;br /&gt;
	delay() {&lt;br /&gt;
		last = null;&lt;br /&gt;
		blocked = 0;&lt;br /&gt;
		quit = 0;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	procedure entry int wait_tick(int nticks) {&lt;br /&gt;
		blocked++;&lt;br /&gt;
		if( nticks &amp;gt; 0 ) { // se un proc entra con nticks = 0 esce direttamente&lt;br /&gt;
			pid_t mypid = getpid();&lt;br /&gt;
			tickmap.add(mypid, nticks);&lt;br /&gt;
			last = mypid&lt;br /&gt;
			while ( tickmap[mypid].tickleft &amp;gt; 0) {&lt;br /&gt;
				waiting4ticks.wait()&lt;br /&gt;
				tickmap[mypid].tickleft --&lt;br /&gt;
				if( last != mypid )&lt;br /&gt;
					waiting4ticks.signal();&lt;br /&gt;
			}&lt;br /&gt;
			map.remove(mypid);&lt;br /&gt;
			if( last == mypid )&lt;br /&gt;
				last = tickleft.getLast(); //se la map è vuota, assumo ritorni null&lt;br /&gt;
		}&lt;br /&gt;
		quit++;&lt;br /&gt;
		return blocked;&lt;br /&gt;
	} &lt;br /&gt;
&lt;br /&gt;
	procedure entry void tick() {&lt;br /&gt;
		waiting4ticks.signal();&lt;br /&gt;
		blocked -= quitted;&lt;br /&gt;
		quit = 0;&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Esercizio c2 ==&lt;br /&gt;
&lt;br /&gt;
=== Consegna ===&lt;br /&gt;
&lt;br /&gt;
Esercizio c.2: Un servizio di message passing asincrono non fifo (nfasend/nfarecv) consegna in tempo finito tutti i&lt;br /&gt;
messaggi spediti ma non è garantito che i messaggi vengano ricevuti nell'ordine nel quale sono stati spediti.&lt;br /&gt;
  void nfasend(msg_t msg, pid_t dest)&lt;br /&gt;
  msg_t nfarecv(pid_t sender)&lt;br /&gt;
Dato un servizio di message passing asincrono non fifo scrivere una libreria che implementi il servizio di message&lt;br /&gt;
passing asincrono fifo:&lt;br /&gt;
  void asend(msg_t msg, pid_t dest)&lt;br /&gt;
  msg_t arecv(pid_t sender)&lt;br /&gt;
Nota: sia il servizio dato (non fifo) sia quello da implementare (fifo) consentono la ricezione solo da mittente specificato&lt;br /&gt;
(non supportano ANY/*).&lt;br /&gt;
&lt;br /&gt;
=== Soluzione proposta 1 ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
void nfasend(msg_t msg, pid_t dest);&lt;br /&gt;
msg_t nfarecv(pid_t sender);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// array di grandezza di massimi numero di processi, inizializzato a 0&lt;br /&gt;
// utilizzato per contare il numero di messaggi inviati a un certo processo.&lt;br /&gt;
int num_sender[MAX_PROC];&lt;br /&gt;
&lt;br /&gt;
//RICORDA che ogni sender ha il suo num_sender[...]&lt;br /&gt;
&lt;br /&gt;
void asend(msg_t msg, pid_t dest) {&lt;br /&gt;
	src = getpid();&lt;br /&gt;
	nfasend(&amp;lt;msg, num_send[dest]&amp;gt;, dest);&lt;br /&gt;
	num_sender[dest]++;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// molto simile a num_sender, ma è utilizzato per contare il numero di messaggi ricevuti, in ordine.&lt;br /&gt;
int num_receiver[MAX_PROC];&lt;br /&gt;
// array heap ordinato sul int (per ogni heap in cima c'è il messaggio col minimo int).&lt;br /&gt;
min_heap&amp;lt;msg, int&amp;gt; messages[MAX_PROC];&lt;br /&gt;
&lt;br /&gt;
//RICORDA che ogni receiver ha il suo proprio num_receiver[...] e messages[...]&lt;br /&gt;
&lt;br /&gt;
msg_t arecv(pid_t sender) {&lt;br /&gt;
	p = getpid();&lt;br /&gt;
	&lt;br /&gt;
	if (messages[sender].size() &amp;gt; 0 &amp;amp;&amp;amp; messages[sender].top() == num_receiver[sender]) {&lt;br /&gt;
		(msg, num_mess) = messages[sender].removeTop();&lt;br /&gt;
		num_receiver[sender]++;&lt;br /&gt;
		return msg;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	(msg, num_mess) = nfarecv(sender);&lt;br /&gt;
&lt;br /&gt;
	while (num_mess != num_receiver[sender]) {&lt;br /&gt;
		messages[sender].insert(msg, num_mess);&lt;br /&gt;
		(msg, num_mess) = nfarecv(sender);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	num_receiver[sender]++;&lt;br /&gt;
	return msg;	&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Soluzione proposta 2 (da controllare) ===&lt;br /&gt;
Proposta da [[User: SpookyWiki |SpookyWiki]] ([[User talk:SpookyWiki|talk]]) 18:42, 22 May 2023 (CEST)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
Map&amp;lt;&amp;lt;pid_t dest, pid_t mitt&amp;gt;, List&amp;lt;int&amp;gt; msgs&amp;gt; db;&lt;br /&gt;
&lt;br /&gt;
void asend(msg_t msg, pid_t dest) { //dobbiamo salvarci l'ordine&lt;br /&gt;
	pid_t mypid = getpid();&lt;br /&gt;
	int progressivo;&lt;br /&gt;
	if (db[&amp;lt;dest, mypid&amp;gt;] == null) {&lt;br /&gt;
		db.add(&amp;lt;dest, mypid&amp;gt;);&lt;br /&gt;
		db[&amp;lt;dest, mypid&amp;gt;].msgs.add(0)&lt;br /&gt;
		progressivo = 0;&lt;br /&gt;
	} else {&lt;br /&gt;
		progressivo = db[&amp;lt;dest, mypid&amp;gt;].msgs.getLast() +1;&lt;br /&gt;
		db[&amp;lt;dest, mypid&amp;gt;].msgs.add(progressivo);&lt;br /&gt;
	}&lt;br /&gt;
	nfasend(&amp;lt;msg, progressivo&amp;gt;, dest);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
msg_t arecv(pid_t sender) {&lt;br /&gt;
	pid_t mypid = getpid();&lt;br /&gt;
	int progressivo = db[&amp;lt;mypid, sender&amp;gt;].msgs[0];&lt;br /&gt;
	msg, prog = nfarecv(sender);&lt;br /&gt;
	while ( prog != progressivo) {&lt;br /&gt;
		nfasend(&amp;lt;msg, progressivo&amp;gt;, mypid);&lt;br /&gt;
		msg, prog = nfarecv(sender);&lt;br /&gt;
	}&lt;br /&gt;
	db[&amp;lt;mypid, sender&amp;gt;].msgs.remove(0);&lt;br /&gt;
	return msg;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Prova 2022/02/14 =&lt;br /&gt;
&lt;br /&gt;
== Esercizio c1 ==&lt;br /&gt;
Scrivere il monitor semdata che implementi un semaforo con dato. Questa astrazione prevede due operazioni:&lt;br /&gt;
&lt;br /&gt;
 datatype dP(void);&lt;br /&gt;
 void dV(datatype data);&lt;br /&gt;
&lt;br /&gt;
Non è previsto assegmento di valore iniziale nel costruttore, l'invariante è lo stesso dei semafori (con init = 0): ndP &amp;lt;=&lt;br /&gt;
ndV (dove ndP e ndV rappresentano rispettivamente il numero di operazioni dP e dV completate. I dati passati come&lt;br /&gt;
parametro alla dV devono essere memorizzati in ordine LIFO. L'operazione nP restituisce il valore più recente fra quelli&lt;br /&gt;
memorizzati (e lo cancella dalla struttura dati).&lt;br /&gt;
&lt;br /&gt;
=== Proposta di soluzione 1 ===&lt;br /&gt;
* Proposta da [[User:Flecart|Flecart]] ([[User talk:Flecart|talk]]) 12:06, 16 January 2023 (CET)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
class semdata {&lt;br /&gt;
&lt;br /&gt;
stack&amp;lt;datatype&amp;gt; pila;&lt;br /&gt;
condition p_waiting;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
semdata() {&lt;br /&gt;
	pila = stack();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
datatype dp(void) {&lt;br /&gt;
	if (pila.len() &amp;lt;= 0) {&lt;br /&gt;
		p_waiting.wait();&lt;br /&gt;
	}	&lt;br /&gt;
&lt;br /&gt;
	return pila.pop();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void dV(datatype data) {&lt;br /&gt;
	pila.push(data);&lt;br /&gt;
	p_waiting.signal();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Esercizio c2 ==&lt;br /&gt;
&lt;br /&gt;
Dato un servizio di message passing asincrono implementare un servizio di message passing sincrono&lt;br /&gt;
con selezione ordinata che ha la seguente interfaccia:&lt;br /&gt;
&lt;br /&gt;
 void snsend(msgtype msg, pid_t dest);&lt;br /&gt;
 msgtype snrecv(pid_t sender, int n);&lt;br /&gt;
&lt;br /&gt;
La funzione snrecv deve restituire l'n-mo messaggio proveniente dal mittente specificato (che può essere any). Se n ==&lt;br /&gt;
0 restituisce l'ultimo messaggio. Esempi:&lt;br /&gt;
m = snrecv(tizio, 1): restituisce il primo messaggio da tizio (attende se non ve ne sono)&lt;br /&gt;
m = snrecv(ANY, 42): restituisce il 42-mo messaggio da chiunque (attende se ci sono meno di 42 messaggi in attesa di&lt;br /&gt;
essere ricevuti)&lt;br /&gt;
m = snrecv(caio, 0): restituisce l'ultimo messaggio ricevuto da Caio (attende se non ci sono messaggi pendenti da Caio)&lt;br /&gt;
m = snrecv(ANY, 0): restituisce l'ultimo messaggio ricevuto, indipendentemente dal mittente.&lt;br /&gt;
&lt;br /&gt;
=== Proposta di soluzione 1 (da controllare)===&lt;br /&gt;
* Proposta da [[User:Barba|zBarba]] ([[User talk:Barba|talk]]) 10:54, 21 January 2024 (CET)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
// int db.count(pid_t sender): conta quanti messaggi inviati da sender sono presenti nel db. Se sender == ANY allora li conta tutti&lt;br /&gt;
// msg_t db.extract(pid_t sender,int  n): ritorna l'n-mo mesaggio del db inviato da sender. Se sender == ANY allora ritorna l'n-mo elemento&lt;br /&gt;
&lt;br /&gt;
void snsend(msgtype msg, pid_t dest){&lt;br /&gt;
    asend(&amp;lt;msg, getpid()&amp;gt;, dest)&lt;br /&gt;
    do{&lt;br /&gt;
        &amp;lt;m, snd&amp;gt; = arecv(dest)&lt;br /&gt;
        db.add(&amp;lt;m, snd&amp;gt;)&lt;br /&gt;
    }while(m != ACK)&lt;br /&gt;
    db.extract(dest, db.count(dest))&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
msgtype snrecv(pid_t sender, int n){&lt;br /&gt;
    if(n == 0){&lt;br /&gt;
        n = db.count(sender)&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    while(db.count(sender) &amp;lt; n){&lt;br /&gt;
        &amp;lt;m, snd&amp;gt; = arecv(sender)&lt;br /&gt;
        db.add(&amp;lt;m, snd&amp;gt;)&lt;br /&gt;
    }&lt;br /&gt;
    &amp;lt;m, snd&amp;gt; = db.extract(sender, n)&lt;br /&gt;
    asend(&amp;lt;ACK, getpid()&amp;gt;, snd)&lt;br /&gt;
    return m&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Prova 2022/01/17 =&lt;br /&gt;
&lt;br /&gt;
== Esercizio c1 ==&lt;br /&gt;
&lt;br /&gt;
Scrivere il monitor multibuf che implementi un buffer limitato (MAX elementi) di oggetti di tipo T che&lt;br /&gt;
implementi le seguenti procedure entry:&lt;br /&gt;
  void add(int n, T objexts[]);&lt;br /&gt;
  void get(int n, T objects[]);&lt;br /&gt;
La funzione add deve aggiungere al buffer gli n oggetti passati col parametro objects. La funzione get deve predere&lt;br /&gt;
dal buffer in modalità FIFO i primi n elementi presenti nel buffer e copiarli negli elementi del vettore objects.&lt;br /&gt;
Entrambe le funzioni devono attendere che vi siano le condizioni per poter essere completate: che ci siano n elementi&lt;br /&gt;
liberi per la add, che ci siano n elementi nel buffer per la get. Non sono ammesse esecuzioni parziali: mentre attendono&lt;br /&gt;
le rispettive condizioni nessun elemento può essere aggiunto o rimosso dal buffer.&lt;br /&gt;
La definizione del problema C.1 presenta casi di possibile deadlock?&lt;br /&gt;
&lt;br /&gt;
=== Soluzione proposta 1 ===&lt;br /&gt;
&lt;br /&gt;
* Proposta [[User:Flecart|Flecart]] ([[User talk:Flecart|talk]]) 12:41, 16 January 2023 (CET)&lt;br /&gt;
&lt;br /&gt;
Una situazione di deadlock è quando un add non ha abbastanza per inserire, e get non ha abbastanza da prendere. Se non utilizzo la coda come ho fatto così&lt;br /&gt;
rischio starvation.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
class multibuf {&lt;br /&gt;
	&lt;br /&gt;
T buffer[MAX];&lt;br /&gt;
int i, j;&lt;br /&gt;
int free;&lt;br /&gt;
queue&amp;lt;int,cond&amp;gt; add_queue;&lt;br /&gt;
&lt;br /&gt;
queue&amp;lt;int,cond&amp;gt; get_queue;&lt;br /&gt;
&lt;br /&gt;
multibuf {&lt;br /&gt;
	i = j = 0;&lt;br /&gt;
	free = MAX;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
void add(int n, T objects[]) {&lt;br /&gt;
	if (add_queue.size() &amp;gt; 0 || free &amp;lt; n) {&lt;br /&gt;
		condition c = new condition();&lt;br /&gt;
		add_queue.enqueue(n, c);&lt;br /&gt;
		c.wait();&lt;br /&gt;
		free(c);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	for (int k = j; k != (j + n) % MAX; k = (k + 1) % MAX) {&lt;br /&gt;
		int other_idx = (k - i) &amp;lt; 0 ? k + MAX - i : k - i;&lt;br /&gt;
		buffer[k] = objects[other_idx];&lt;br /&gt;
	}&lt;br /&gt;
	free -= n;&lt;br /&gt;
	j = (j + n) % MAX;&lt;br /&gt;
		&lt;br /&gt;
	while (get_queue.size() &amp;gt; 0 &amp;amp;&amp;amp; get_queue.front() &amp;lt;= MAX - free) {&lt;br /&gt;
		n, cond = get_queue.dequeue();&lt;br /&gt;
		cond.signal();&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void get(int n, T objects[]) {&lt;br /&gt;
	if (get_queue.size() &amp;gt; 0 || MAX - free &amp;lt; n) {&lt;br /&gt;
		condition c = new condition();&lt;br /&gt;
		get_queue.enqueue(n, c);&lt;br /&gt;
		c.wait();&lt;br /&gt;
		free(c);&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	for (int k = i; k != (i + n) % MAX; k = (k + 1) % MAX) {&lt;br /&gt;
		int other_idx = (k - i) &amp;lt; 0 ? k + MAX - i : k - i;&lt;br /&gt;
		objects[other_idx] = buffer[k];&lt;br /&gt;
	}&lt;br /&gt;
	free += n;&lt;br /&gt;
	i = (i + n) % MAX;&lt;br /&gt;
&lt;br /&gt;
	while (add_queue.size() &amp;gt; 0 &amp;amp;&amp;amp; add_queue.front() &amp;lt;= free) {&lt;br /&gt;
		n, cond = add_queue.dequeue();&lt;br /&gt;
		cond.signal();&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
} // multibuf&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Esercizio c2 ==&lt;br /&gt;
Un servizio di message passing sincrono senza selezione del mittente prevede una API con due funzioni:&lt;br /&gt;
  sasend(msg_t msg, pid dest);&lt;br /&gt;
  msg_t sarecv(void);&lt;br /&gt;
La funzione sarecv restituisce il primo messaggio ricevuto da qualsiasi mittente ed è bloccante se non ci sono&lt;br /&gt;
messaggi pendenti. la funzione sasend si blocca fino a quando il messaggio msg non viene ricevuto dal processo dest.&lt;br /&gt;
Dato quindi un servizio di message passing sincrono senza selezione del mittente implementare un servizio di&lt;br /&gt;
message passing sincrono (standard, quello definito nel corso) senza fare uso di processi server. &lt;br /&gt;
&lt;br /&gt;
=== Soluzione proposta 1 (da controllare) ===&lt;br /&gt;
* proposta da [[User:Flecart|Flecart]] ([[User talk:Flecart|talk]]) 18:25, 16 January 2023 (CET) &lt;br /&gt;
* Errore, ssend in questo caso non è sincrono, bisognerebbe uscire con l'ack dal receiver [[User:Flecart|Flecart]] ([[User talk:Flecart|talk]]) 22:56, 16 January 2023 (CET)&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
ssend(msg_t msg, pid dest) {&lt;br /&gt;
	sasend(&amp;lt;msg, getpid()&amp;gt;, dest);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// variabili interne di srecv&lt;br /&gt;
queue&amp;lt;msg_t&amp;gt; msgs[MAX_PROC];&lt;br /&gt;
&lt;br /&gt;
// suppongo non ci sia il caso in cui sender = ANY.&lt;br /&gt;
// nel caso ci fosse la necessità, si dovrebbe creare una altra struttura di dati&lt;br /&gt;
// che ordini globalmente il messaggio che sia arrivato prima.&lt;br /&gt;
msg_t srecv(pid sender) {&lt;br /&gt;
	if (msgs[sender].len() &amp;gt; 0) {&lt;br /&gt;
		return msgs[sender].dequeue();&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	while (true) {&lt;br /&gt;
		&amp;lt;msg, pid&amp;gt; = sarecv();&lt;br /&gt;
		if (pid == sender) {&lt;br /&gt;
			return msgs[pid].dequeue();&lt;br /&gt;
		} else {&lt;br /&gt;
			msgs[pid].enqueue(msg);&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Soluzione proposta 2 (da controllare) ===&lt;br /&gt;
&lt;br /&gt;
proposta da [[User:gio|Flecart Friend]] cedo la proprità intellettuale di questa soluzione a flecart&lt;br /&gt;
 &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
// mem è condivisa tra ssend e srecv di ogni processo&lt;br /&gt;
// essendo che un processo può solo mandare o ricevere alla volta&lt;br /&gt;
// non abbiamo bisogno di cs&lt;br /&gt;
&lt;br /&gt;
// inizializzati tutti a NULL&lt;br /&gt;
msg_t mem[MAXPID];&lt;br /&gt;
// in mem ci basta un messaggio per PID perchè un pid può aver mandato al&lt;br /&gt;
// massimo un messaggio essendo che sono bloccanti la send e la recive&lt;br /&gt;
&lt;br /&gt;
void ssend(msg_t msg, pid dest) {&lt;br /&gt;
  sasend(&amp;lt;getpid(),msg&amp;gt;,dest);&lt;br /&gt;
  while(true){&lt;br /&gt;
    &amp;lt;form_c,msg&amp;gt;=sarecv();&lt;br /&gt;
    // dovrebbe essere ovvio che se è from c allora il msg dovrebbe essere un&lt;br /&gt;
    // ack perchè se c avesse mandato un messaggio diverso vorrebbe dire che&lt;br /&gt;
    // sta facendo una send e se i due processi si fanno una send allora c'è&lt;br /&gt;
    // deadhlock&lt;br /&gt;
    if(from_c == dest &amp;amp;&amp;amp; msg == ACK){&lt;br /&gt;
      break;&lt;br /&gt;
    }else{&lt;br /&gt;
      mem[from_c]=msg;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
msg_t srecv(pid from) {&lt;br /&gt;
  if(mem[from]!=NULL){&lt;br /&gt;
    t=mem[from];&lt;br /&gt;
    mem[from]=NULL;&lt;br /&gt;
    ssend(ACK,from);&lt;br /&gt;
    return t;&lt;br /&gt;
  }&lt;br /&gt;
  while(true){&lt;br /&gt;
    &amp;lt;form_c,msg&amp;gt;=sarecv();&lt;br /&gt;
    if(from_c==from){&lt;br /&gt;
      ssend(ACK,from);&lt;br /&gt;
      return msg;&lt;br /&gt;
    }else{&lt;br /&gt;
      mem[from_c].push(msg);&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>Barba</name></author>
	</entry>
	<entry>
		<id>https://so.v2.cs.unibo.it/wiki/index.php?title=Prove_scritte_2022&amp;diff=3066</id>
		<title>Prove scritte 2022</title>
		<link rel="alternate" type="text/html" href="https://so.v2.cs.unibo.it/wiki/index.php?title=Prove_scritte_2022&amp;diff=3066"/>
		<updated>2024-01-21T09:54:03Z</updated>

		<summary type="html">&lt;p&gt;Barba: /* Prova 2022/02/14 */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Prova 2022/09/06 =&lt;br /&gt;
&lt;br /&gt;
== Esercizio c1 == &lt;br /&gt;
&lt;br /&gt;
Esercizio c.1: I bit di un numero intero rappresentano condizioni di un sistema. Se lo stato attuale è 6 (0110) vuole dire&lt;br /&gt;
che attualmente sono vere le condizioni 2 (0010) e 4 (0100).&lt;br /&gt;
Scrivere un monitor bitcond che fornisca le seguenti procedure entry:&lt;br /&gt;
void set(int bit2set); accende nello stato attuale i bit di bit2set&lt;br /&gt;
void unset(int bit2unset) spegne nello stato attuale i bit di bit2unset&lt;br /&gt;
void statuswait(int bit2wait) attende che lo stato attuale soddisfi tutti le condizioni indicate in bit2wait (cioè&lt;br /&gt;
che tutti i bit in bit2wait siano accesi nello stato attuale).&lt;br /&gt;
Le richieste statuswait devono essere servite in ordine FIFO (cioè un processo anche se sono presenti tutte le&lt;br /&gt;
condizioni necessarie deve attendere se un processo che ha chiamato statuswait prima è in attesa).&lt;br /&gt;
Lo stato iniziale è zero (nessuna risorsa disponibile)&lt;br /&gt;
&lt;br /&gt;
=== Soluzione proposta 1 ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
class bitcond{&lt;br /&gt;
  int bitmap;&lt;br /&gt;
  int lastBitmask;&lt;br /&gt;
  int has=0;&lt;br /&gt;
  &lt;br /&gt;
  condition waiting;&lt;br /&gt;
  condition c;&lt;br /&gt;
&lt;br /&gt;
  void set(int i){&lt;br /&gt;
    bitmap|=i; &lt;br /&gt;
      if(bitmap&amp;amp;lastBitmask == bitmap) c.signal();&lt;br /&gt;
  }&lt;br /&gt;
  void unset(int i){&lt;br /&gt;
    bitmap&amp;amp;=~i; &lt;br /&gt;
  }&lt;br /&gt;
  void statuswait(int i){&lt;br /&gt;
    has++; &lt;br /&gt;
    if(has&amp;gt;1){&lt;br /&gt;
      waiting.wait();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if(!(bitmap&amp;amp;i==i)){&lt;br /&gt;
      lastBitmask=i;&lt;br /&gt;
      c.wait();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    waiting.signal();&lt;br /&gt;
    has--;&lt;br /&gt;
  }&lt;br /&gt;
  bitcond(){&lt;br /&gt;
    bitmap = 0;&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Soluzione proposta 2 ===&lt;br /&gt;
Proposta da [[User:Flecart|Flecart]] ([[User talk:Flecart|talk]]) 12:06, 14 January 2023 (CET)&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
&lt;br /&gt;
const int int_size = 32;&lt;br /&gt;
&lt;br /&gt;
class monitor {&lt;br /&gt;
    int value;&lt;br /&gt;
    condition bitset[int_size];&lt;br /&gt;
&lt;br /&gt;
    int numstatuswaiting;&lt;br /&gt;
    condition waiting;&lt;br /&gt;
    &lt;br /&gt;
    monitor() {&lt;br /&gt;
        value = 0;&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    /// guarda se il bit n-significativo è settato in from&lt;br /&gt;
    bool nbit(int from, int n) {&lt;br /&gt;
        return (from &amp;amp; (1 &amp;lt;&amp;lt; n)) != 0&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    void entry set(int bit2set) {&lt;br /&gt;
        value |= bit2set;&lt;br /&gt;
&lt;br /&gt;
        for (int i = 0; i &amp;lt; 32; i++) {&lt;br /&gt;
            if (nbit(value, i))&lt;br /&gt;
                bitset[i].signal();&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    void entry statuswait(int bit2wait) {&lt;br /&gt;
        // in questo modo solamente un singolo processo è dentro ad aspettare&lt;br /&gt;
        // che tutte le condizioni siano rispettate&lt;br /&gt;
        if (numstatuswaiting &amp;gt; 0)&lt;br /&gt;
            waiting.wait();&lt;br /&gt;
        &lt;br /&gt;
        numstatuswaiting++;&lt;br /&gt;
        int i = 0;&lt;br /&gt;
        while(i &amp;lt; 32) {&lt;br /&gt;
            if (nbit(bit2wait, i) &amp;amp;&amp;amp; !nbit(value, i)) {&lt;br /&gt;
                bitset[i].wait();&lt;br /&gt;
&lt;br /&gt;
                // ricomincia a guardare tutti i bit da zero, perché&lt;br /&gt;
                // nel frattempo potrebbero essere cambiati.&lt;br /&gt;
                // -1 così con l'istruzione successiva diventa 0&lt;br /&gt;
                i = -1; &lt;br /&gt;
            }&lt;br /&gt;
            i++;&lt;br /&gt;
        }&lt;br /&gt;
        &lt;br /&gt;
        numstatuswaiting--;&lt;br /&gt;
        waiting.signal();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Soluzione proposta 3 ===&lt;br /&gt;
Proposta da [[User:Flecart|Flecart]] ([[User talk:Flecart|talk]]) 12:07, 14 January 2023 (CET)&lt;br /&gt;
questa è la soluzione più brutta, ma dovrebbe andare.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
&lt;br /&gt;
const int int_size = 32;&lt;br /&gt;
&lt;br /&gt;
class monitor {&lt;br /&gt;
    int value;&lt;br /&gt;
    condition status;&lt;br /&gt;
&lt;br /&gt;
    int numstatuswaiting;&lt;br /&gt;
    condition waiting;&lt;br /&gt;
    &lt;br /&gt;
    monitor() {&lt;br /&gt;
        value = 0;&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    /// guarda se il bit n-significativo è settato in from&lt;br /&gt;
    bool nbit(int from, int n) {&lt;br /&gt;
        return (from &amp;amp; (1 &amp;lt;&amp;lt; n)) != 0&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    void entry set(int bit2set) {&lt;br /&gt;
        value |= bit2set;&lt;br /&gt;
        status.signal();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
    void entry unset(int bit2unset) {&lt;br /&gt;
        value = (value &amp;amp; ~bit2unset);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    void entry statuswait(int bit2wait) {&lt;br /&gt;
        // in questo modo solamente un singolo processo è dentro ad aspettare&lt;br /&gt;
        // che tutte le condizioni siano rispettate&lt;br /&gt;
        if (numstatuswaiting &amp;gt; 0)&lt;br /&gt;
            waiting.wait();&lt;br /&gt;
        &lt;br /&gt;
        numstatuswaiting++;&lt;br /&gt;
        while(true) {&lt;br /&gt;
            if ((value &amp;amp; bit2wait) == bit2wait) &lt;br /&gt;
                break;&lt;br /&gt;
            else &lt;br /&gt;
                status.wait();&lt;br /&gt;
        }&lt;br /&gt;
        numstatuswaiting--;&lt;br /&gt;
        waiting.signal();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Esercizio c2 ==&lt;br /&gt;
&lt;br /&gt;
[[ 20220906c2 ]]  proposte di soluzione&lt;br /&gt;
&lt;br /&gt;
= Prova 2022/07/20 =&lt;br /&gt;
&lt;br /&gt;
== Esercizio c1 == &lt;br /&gt;
&lt;br /&gt;
in un porto con una sola banchina utilizzabile occorre caricare cereali sulle navi. I camion portano i cereali al porto. Una sola nave alla volta può essere attraccata al molo, un solo camion alla volta scarica i cereali nella nave.&lt;br /&gt;
Il codice eseguito da ogni nave è:&lt;br /&gt;
   nave[i] process:&lt;br /&gt;
     porto.attracca(capacità) &lt;br /&gt;
     porto.salpa()&lt;br /&gt;
     ...naviga verso la destinazione&lt;br /&gt;
&lt;br /&gt;
Il codice di ogni camion è:&lt;br /&gt;
  camion[j] process: &lt;br /&gt;
    while (1):&lt;br /&gt;
      quantità = carica_cereali()&lt;br /&gt;
      porto.scarica(quantità)&lt;br /&gt;
&lt;br /&gt;
I camion fanno la spola dai depositi alla nave. La nave arriva vuota e può salpare solo se è stata completamente riempita (la somma delle quantità scaricate dai camion raggiunge la capacità indicata come parametro della funzione attracca). Se un camion può scaricare solo parzialmente il suo carico rimane in porto e aspetta di completare l'operazione con la prossima nave che attraccherà al molo.&lt;br /&gt;
Scrivere il monitor porto.&lt;br /&gt;
&lt;br /&gt;
=== Soluzione proposta 1 (da controllare) ===&lt;br /&gt;
Proposta da [[User: SpookyWiki |SpookyWiki]] ([[User talk:SpookyWiki|talk]]) 14:56, 13 May 2023 (CEST)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
&lt;br /&gt;
// in questa versione, se il remainingSpace è -1 vuol dire che nessuna &lt;br /&gt;
	//barca è attraccata&lt;br /&gt;
monitor porto{&lt;br /&gt;
&lt;br /&gt;
	int remainingSpace; // -1 -&amp;gt; non ci sono barche attraccate&lt;br /&gt;
	bool camionSlotBusy;&lt;br /&gt;
	condition waiting4slot; //il camion attende di essere preso in carico&lt;br /&gt;
	condition waiting4dock; //la barca attende il molo&lt;br /&gt;
	condition waiting4load; //il la barca attende i camion&lt;br /&gt;
	condition waiting4boat; //i camion attendono una barca&lt;br /&gt;
&lt;br /&gt;
	porto {&lt;br /&gt;
		remainingSpace = -1;&lt;br /&gt;
		camionSlotBusy = false;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	procedure entry void attracca(int capacità){&lt;br /&gt;
		if( remainingSpace &amp;gt;=0 )&lt;br /&gt;
			wait4dock.wait();&lt;br /&gt;
		remainingSpace = capacità;&lt;br /&gt;
		waiting4slot.signal();&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	procedure entry void salpa(){&lt;br /&gt;
		if( remainingSpace &amp;gt; 0 )&lt;br /&gt;
			wait4load.wait();&lt;br /&gt;
		waiting4dock.signal();&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	procedure entry void scarica(quantità){&lt;br /&gt;
		if( camionSlotBusy ) &lt;br /&gt;
			waiting4slot.wait()&lt;br /&gt;
		//se non posso scaricare il carico&lt;br /&gt;
		if( remainingSpace &amp;lt;= 0)&lt;br /&gt;
			waiting4boat.wait()&lt;br /&gt;
&lt;br /&gt;
		int remainingLoad = quantità;&lt;br /&gt;
&lt;br /&gt;
		while (remainingLoad &amp;gt; 0){&lt;br /&gt;
			//il camion si svuota e se ne deve andare&lt;br /&gt;
			if( remainingSpace &amp;gt;= remainingLoad ) {&lt;br /&gt;
				remainingSpace -= remainingLoad;&lt;br /&gt;
				remainingLoad = 0;&lt;br /&gt;
				if ( remainingSpace == 0)&lt;br /&gt;
					wait4load.signal();&lt;br /&gt;
			//il camion non si svuota del tutto e deve rimanere&lt;br /&gt;
			} else {&lt;br /&gt;
				remainingLoad -= remainingSpace;&lt;br /&gt;
				remainingSpace = 0;&lt;br /&gt;
				waiting4load.signal();&lt;br /&gt;
				waiting4boat.wait();&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
		waiting4slot.singal();&lt;br /&gt;
		&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Prova 2022/06/21 =&lt;br /&gt;
&lt;br /&gt;
== Esercizio c1 ==&lt;br /&gt;
Scrivere il monitor collocamento:&lt;br /&gt;
  void cercolavoro(char *nome, char *skill)&lt;br /&gt;
  void char *assumo(char * skill)&lt;br /&gt;
Quando un processo chiama la cercolavoro si mette in attesa di una richiesta di lavoro e rimane bloccato nel monitor&lt;br /&gt;
fino a che non è stato assunto. Nella cercolavoro viene indicato il nome dell'aspirante lavoratore la sua capacità (skill).&lt;br /&gt;
Un datore di lavoro con necessità di personale chiama la assumo specificando la capacità richiesta. Se c'è in attesa&lt;br /&gt;
almeno un aspirante lavoratore con quella specifica capacità (uguale valore di skill), il datore di lavoro riceve il nome del&lt;br /&gt;
nuovo dipendente ed entrambi i processi escono dal monitor. Nel caso non ci siano richieste compatibili il datore di&lt;br /&gt;
lavoro si blocca nel monitor attendendo un lavoratore con la capacità cercata. Quando arriva il lavoratore che soddisfa&lt;br /&gt;
le richieste si sbloccano entrambi i processi lavoratore e datore di lavoro. La assumo restituisce in ogni caso il nome del&lt;br /&gt;
dipendente da assumere.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Soluzione proposta === &lt;br /&gt;
&lt;br /&gt;
Soluzione proposta da [[User:Flecart|Flecart]] ([[User talk:Flecart|talk]]) 12:08, 14 January 2023 (CET)&lt;br /&gt;
&lt;br /&gt;
ci potrebbe essere un errore in quanto non è specificato il comportamento della struttura dati in alcune situazioni&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
&lt;br /&gt;
class collocamento{&lt;br /&gt;
&lt;br /&gt;
set&amp;lt;char *, condition&amp;gt; richieste;  // chi assume cerca questa skill&lt;br /&gt;
set&amp;lt;char *, char *, condition&amp;gt; ricerche; // nome e skill di chi cerca&lt;br /&gt;
&lt;br /&gt;
char *last_nome;&lt;br /&gt;
&lt;br /&gt;
collocamento {&lt;br /&gt;
	last_nome = NULL;&lt;br /&gt;
	richieste = set();&lt;br /&gt;
	ricerche = set();	&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void cercolavoro(char *nome, char *skill) {&lt;br /&gt;
	datore = richieste.find(skill);  // cerca valutando la prima come chiave&lt;br /&gt;
	if (datore != NULL) {&lt;br /&gt;
		&amp;lt;skill, cond&amp;gt; = datore;&lt;br /&gt;
		richieste.remove(datore);&lt;br /&gt;
		last_nome = nome;&lt;br /&gt;
		cond.signal();		&lt;br /&gt;
	} else {&lt;br /&gt;
		condition c = new condition();&lt;br /&gt;
		ricerche.insert(nome, skill, c);&lt;br /&gt;
		c.wait();&lt;br /&gt;
		free(c);&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void char *assumo(char * skill){&lt;br /&gt;
	lavoratore = ricerche.find2(skill); // cerca valutando la seconda come chiave.&lt;br /&gt;
	if (lavoratore != NULL) {&lt;br /&gt;
		&amp;lt;nome, skill, cond&amp;gt; = lavoratore;&lt;br /&gt;
		ricerche.remove(lavoratore);&lt;br /&gt;
		cond.signal();&lt;br /&gt;
		last_nome = nome;&lt;br /&gt;
	} else {&lt;br /&gt;
		condition c = new condition();&lt;br /&gt;
		richieste.insert(skill, c);&lt;br /&gt;
		c.wait();&lt;br /&gt;
		free(c);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	return last_nome;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
}// class collocamento&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Soluzione proposta === &lt;br /&gt;
&lt;br /&gt;
Soluzione proposta da [[User:Flecart|Flecart Frend]], regalo la proprietà intellettuale di questa soluzione a flecart.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
class workdisptcher{&lt;br /&gt;
&lt;br /&gt;
  // la multi map può storare più di un valore per una chiave&lt;br /&gt;
  // quando viene richiesta una particolare chiave da in maniera LIFO&lt;br /&gt;
  // il risultato&lt;br /&gt;
  // es:&lt;br /&gt;
  // multi_map&amp;lt;char *,int&amp;gt; lavoratori;&lt;br /&gt;
  // lavoratori.insert(&amp;quot;prova&amp;quot;,2);&lt;br /&gt;
  // lavoratori.insert(&amp;quot;prova&amp;quot;,1);&lt;br /&gt;
  // lavoratori.get(&amp;quot;prova&amp;quot;) == 2&lt;br /&gt;
  // lavoratori.remove(&amp;quot;prova&amp;quot;)&lt;br /&gt;
  // lavoratori.get(&amp;quot;prova&amp;quot;) == 1&lt;br /&gt;
  multi_map&amp;lt;char *,(char*,cond)&amp;gt; lavoratori;&lt;br /&gt;
  multi_map&amp;lt;char *,cond&amp;gt; posti_aperti;&lt;br /&gt;
  char* buffer_name;&lt;br /&gt;
  void cercolavoro(char *nome, char *skill){&lt;br /&gt;
    if(posti_aperti.find(skill)){&lt;br /&gt;
      auto entry =posti_aperti.get(skill);&lt;br /&gt;
      posti_aperti.remove(entry);&lt;br /&gt;
      buffer_name=name;&lt;br /&gt;
      entry.1.signal();&lt;br /&gt;
    }else{&lt;br /&gt;
      cond c= new cond();&lt;br /&gt;
      lavoratori.insert(skill,(nome,c)) ;&lt;br /&gt;
      c.wait();&lt;br /&gt;
      free(c);&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
  void char *assumo(char * skill){&lt;br /&gt;
    if(lavoratori.find(skill)){&lt;br /&gt;
      auto entry =lavoratori.get(skill);&lt;br /&gt;
      posti_aperti.remove(entry);&lt;br /&gt;
      auto [nome,cnd] = entry.1;&lt;br /&gt;
      cond.signal();&lt;br /&gt;
      return nome;&lt;br /&gt;
    }else{&lt;br /&gt;
      cond c= new cond();&lt;br /&gt;
      posti_aperti.insert(skill,c) ;&lt;br /&gt;
      c.wait();&lt;br /&gt;
      free(c);&lt;br /&gt;
      return buffer_name;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Esercizio c2 ==&lt;br /&gt;
Un servizio viene fornito in modalità client-server usando message passing asincrono.&lt;br /&gt;
Al fine di aumentare l'efficienza si decide di usare molti server e un processo dispatcher in grado di distribuire le&lt;br /&gt;
richieste agli N server. Quando un processo server è libero riceve dal dispatcher la prossima richiesta da elaborare:&lt;br /&gt;
codice di ogni client (tanti!): .....&lt;br /&gt;
  asend(&amp;lt;getpid(), request&amp;gt;, dispatcher)&lt;br /&gt;
  result = arecv(dispatcher)&lt;br /&gt;
&lt;br /&gt;
server process[i], i = 0, ..., N-1:&lt;br /&gt;
 request = arecv(dispatcher)&lt;br /&gt;
 result = compute(request)&lt;br /&gt;
 asend(&amp;lt;getpid(), result&amp;gt;, dispatcher)&lt;br /&gt;
Scrivere il processo dispatcher. (il dispatcher conosce i pid di tutti i server).&lt;br /&gt;
&lt;br /&gt;
=== Soluzione proposta (sbagliata) === &lt;br /&gt;
&lt;br /&gt;
Soluzione proposta da [https://so.v2.cs.unibo.it/wiki/index.php/User:Flecart Flecart] &lt;br /&gt;
&lt;br /&gt;
Questo esercizio è stato corretto tempo fa in classe dal professore, **non è completamente corretto** se si vuole provare a correggerlo alla fine dell'esercizio c'è scritto cos'è sbagliato.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
&lt;br /&gt;
extern int N;&lt;br /&gt;
process dispatcher() {&lt;br /&gt;
    // indice che tiene conto a quale server dover mandare&lt;br /&gt;
    // per semplicità supponiamo che i server abbiano PID&lt;br /&gt;
    // da 0 a N - 1&lt;br /&gt;
    int i = 0; &lt;br /&gt;
&lt;br /&gt;
    // mappa server a pid del processo che lo ha richiesto.&lt;br /&gt;
    // chiave: pid del server&lt;br /&gt;
    // value: queue richiesta dispatchata al server in chiave&lt;br /&gt;
    map&amp;lt;int, queue&amp;lt;int&amp;gt;&amp;gt; mapper; &lt;br /&gt;
    while (true) {&lt;br /&gt;
        res = arecv(ANY);&lt;br /&gt;
        &lt;br /&gt;
        // in questa parte l'importante è sapere&lt;br /&gt;
        // se la richiesta proviene dal  server o da un altro&lt;br /&gt;
        // processo, ho assunto che la disambiguazione &lt;br /&gt;
        // fosse immediata, un altro modo per checkare questo&lt;br /&gt;
        // è vedere se il PID del messaggio rientri fra quelli&lt;br /&gt;
        // noti al dispatcher.&lt;br /&gt;
        if (&amp;lt;pid, request&amp;gt; = res) {&lt;br /&gt;
            mapper[i].enqueue(pid);&lt;br /&gt;
            asend(request, i /*il i-esimo server*/);&lt;br /&gt;
            i++;&lt;br /&gt;
            i %= N;&lt;br /&gt;
        } else if (&amp;lt;pid, response&amp;gt; = res) {&lt;br /&gt;
            requester_pid = mapper[pid].dequeue();&lt;br /&gt;
            asend(response, requester_pid);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
l'es è sbagliato perchè dovrei mandare ai server liberi, non a round-robin [[User:Flecart|Flecart]] ([[User talk:Flecart|talk]]) 15:52, 14 January 2023 (CET)&lt;br /&gt;
&lt;br /&gt;
=== Soluzione proposta 2 === &lt;br /&gt;
&lt;br /&gt;
Soluzione proposta da [https://so.v2.cs.unibo.it/wiki/index.php/User:Gio Giovanni Spadaccini] &lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
dispatcher{&lt;br /&gt;
  queue&amp;lt;&amp;lt;pid,request&amp;gt;&amp;gt; work;&lt;br /&gt;
  queue&amp;lt;pid&amp;gt; freeserver;&lt;br /&gt;
  map&amp;lt;pid,pid&amp;gt; map_server_to_client;&lt;br /&gt;
  while(true){&lt;br /&gt;
    &amp;lt;pid,message&amp;gt;=arecv(ANY);&lt;br /&gt;
    if pid in servers{&lt;br /&gt;
      client=map_server_to_client.get(pid);&lt;br /&gt;
      map_client_to_server.remove(pid);&lt;br /&gt;
      freeserver.push(pid);&lt;br /&gt;
      asend(&amp;lt;message&amp;gt;,client);&lt;br /&gt;
    }else{&lt;br /&gt;
      work.push(&amp;lt;pid,message&amp;gt;);&lt;br /&gt;
    }&lt;br /&gt;
    while !freeserver.empty() and !work.emtpy(){&lt;br /&gt;
      server_pid = freeserver.pop();&lt;br /&gt;
      &amp;lt;client,msg&amp;gt; = work.pop();&lt;br /&gt;
      map_server_to_client.insert(server,client);&lt;br /&gt;
      asend(msg,server_pid);&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Prova 2022/06/01 =&lt;br /&gt;
&lt;br /&gt;
== Esercizio c1 ==&lt;br /&gt;
&lt;br /&gt;
Scrivere il monitor delay che fornisce due procedure entry:&lt;br /&gt;
  int wait_tick(int nticks)&lt;br /&gt;
  void tick(void)&lt;br /&gt;
La procedure entry tick è pensata per essere richiamata periodicamente (es. ogni secondo o ora o giorno) da un&lt;br /&gt;
processo.&lt;br /&gt;
Quando un processo chiama la wait_tick deve attendere un numero di chiamate della tick pari al parametro nticks.&lt;br /&gt;
Per esempio se un processo chiama wait_tick(2) deve fermarsi e verrà riattivato alla seconda successiva chiamata di&lt;br /&gt;
tick.&lt;br /&gt;
La funzione wait_tick ha come valore di ritorno il numero di processi che erano bloccati al momento della tick che ha&lt;br /&gt;
sbloccato il chiamante.&lt;br /&gt;
Esempio: P chiama wait_tick(2) e si blocca. Q chiama wait_tick(3) e si blocca. T chiama tick() non succede nulla. R&lt;br /&gt;
chiama wait_tick(2) e si blocca. T chiama tick(), viene sbloccata la wait_tick di P e il valore ritornato è 3. T chiama&lt;br /&gt;
tick(), vengono sbloccate le wait_tick di Q e R e il valore ritornato per entrambi i processi è 2&lt;br /&gt;
&lt;br /&gt;
=== Soluzione proprosta 1 (da controllare) ===&lt;br /&gt;
Soluzione proposta da [https://so.v2.cs.unibo.it/wiki/index.php/User:Flecart Flecart] &lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
&lt;br /&gt;
class MonitorDelay {&lt;br /&gt;
    int curr_time;&lt;br /&gt;
    int waiting_num;&lt;br /&gt;
&lt;br /&gt;
    // min heap con il tempo di sblocco dei processi e la condizione su cui è fermato&lt;br /&gt;
    // il tempo di sblocco minore è messo in cima alla heap&lt;br /&gt;
    // la sintassi con pair è ispirata alla std::pair di c++&lt;br /&gt;
    heap&amp;lt;pair&amp;lt;int, condition&amp;gt;&amp;gt; waiting; &lt;br /&gt;
&lt;br /&gt;
    void init() {&lt;br /&gt;
        curr_time = 0;&lt;br /&gt;
        waiting = heap&amp;lt;pair&amp;lt;int, condition&amp;gt;&amp;gt;();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    int entry wait_tick(int nticks) {&lt;br /&gt;
        if (nticks &amp;lt;= 0) {&lt;br /&gt;
            return waiting.size();&lt;br /&gt;
        } else {&lt;br /&gt;
            condition c = new condition();&lt;br /&gt;
            waiting.insert(make_pair(nticks + curr_time, c));&lt;br /&gt;
            c.wait();&lt;br /&gt;
            free(c);&lt;br /&gt;
        }&lt;br /&gt;
        return waiting_num;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
    void entry tick(void) {&lt;br /&gt;
        waiting_num = waiting.size();&lt;br /&gt;
        curr_time++;&lt;br /&gt;
&lt;br /&gt;
        while (waiting.head().first &amp;lt;= curr_time) {&lt;br /&gt;
            condition c = waiting.head().second;&lt;br /&gt;
            waiting.deleteHead();&lt;br /&gt;
            c.signal();&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Soluzione proposta 2 (da controllare) ===&lt;br /&gt;
Proposta da [[User: SpookyWiki |SpookyWiki]] ([[User talk:SpookyWiki|talk]]) 18:06, 22 May 2023 (CEST)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
monitor delay {&lt;br /&gt;
	Map&amp;lt;pid_t, int tickleft&amp;gt; tickmap;&lt;br /&gt;
	pid_t last;&lt;br /&gt;
	int blocked;&lt;br /&gt;
	int quit;&lt;br /&gt;
	condition wait4ticks;&lt;br /&gt;
	&lt;br /&gt;
	delay() {&lt;br /&gt;
		last = null;&lt;br /&gt;
		blocked = 0;&lt;br /&gt;
		quit = 0;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	procedure entry int wait_tick(int nticks) {&lt;br /&gt;
		blocked++;&lt;br /&gt;
		if( nticks &amp;gt; 0 ) { // se un proc entra con nticks = 0 esce direttamente&lt;br /&gt;
			pid_t mypid = getpid();&lt;br /&gt;
			tickmap.add(mypid, nticks);&lt;br /&gt;
			last = mypid&lt;br /&gt;
			while ( tickmap[mypid].tickleft &amp;gt; 0) {&lt;br /&gt;
				waiting4ticks.wait()&lt;br /&gt;
				tickmap[mypid].tickleft --&lt;br /&gt;
				if( last != mypid )&lt;br /&gt;
					waiting4ticks.signal();&lt;br /&gt;
			}&lt;br /&gt;
			map.remove(mypid);&lt;br /&gt;
			if( last == mypid )&lt;br /&gt;
				last = tickleft.getLast(); //se la map è vuota, assumo ritorni null&lt;br /&gt;
		}&lt;br /&gt;
		quit++;&lt;br /&gt;
		return blocked;&lt;br /&gt;
	} &lt;br /&gt;
&lt;br /&gt;
	procedure entry void tick() {&lt;br /&gt;
		waiting4ticks.signal();&lt;br /&gt;
		blocked -= quitted;&lt;br /&gt;
		quit = 0;&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Esercizio c2 ==&lt;br /&gt;
&lt;br /&gt;
=== Consegna ===&lt;br /&gt;
&lt;br /&gt;
Esercizio c.2: Un servizio di message passing asincrono non fifo (nfasend/nfarecv) consegna in tempo finito tutti i&lt;br /&gt;
messaggi spediti ma non è garantito che i messaggi vengano ricevuti nell'ordine nel quale sono stati spediti.&lt;br /&gt;
  void nfasend(msg_t msg, pid_t dest)&lt;br /&gt;
  msg_t nfarecv(pid_t sender)&lt;br /&gt;
Dato un servizio di message passing asincrono non fifo scrivere una libreria che implementi il servizio di message&lt;br /&gt;
passing asincrono fifo:&lt;br /&gt;
  void asend(msg_t msg, pid_t dest)&lt;br /&gt;
  msg_t arecv(pid_t sender)&lt;br /&gt;
Nota: sia il servizio dato (non fifo) sia quello da implementare (fifo) consentono la ricezione solo da mittente specificato&lt;br /&gt;
(non supportano ANY/*).&lt;br /&gt;
&lt;br /&gt;
=== Soluzione proposta 1 ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
void nfasend(msg_t msg, pid_t dest);&lt;br /&gt;
msg_t nfarecv(pid_t sender);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// array di grandezza di massimi numero di processi, inizializzato a 0&lt;br /&gt;
// utilizzato per contare il numero di messaggi inviati a un certo processo.&lt;br /&gt;
int num_sender[MAX_PROC];&lt;br /&gt;
&lt;br /&gt;
//RICORDA che ogni sender ha il suo num_sender[...]&lt;br /&gt;
&lt;br /&gt;
void asend(msg_t msg, pid_t dest) {&lt;br /&gt;
	src = getpid();&lt;br /&gt;
	nfasend(&amp;lt;msg, num_send[dest]&amp;gt;, dest);&lt;br /&gt;
	num_sender[dest]++;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// molto simile a num_sender, ma è utilizzato per contare il numero di messaggi ricevuti, in ordine.&lt;br /&gt;
int num_receiver[MAX_PROC];&lt;br /&gt;
// array heap ordinato sul int (per ogni heap in cima c'è il messaggio col minimo int).&lt;br /&gt;
min_heap&amp;lt;msg, int&amp;gt; messages[MAX_PROC];&lt;br /&gt;
&lt;br /&gt;
//RICORDA che ogni receiver ha il suo proprio num_receiver[...] e messages[...]&lt;br /&gt;
&lt;br /&gt;
msg_t arecv(pid_t sender) {&lt;br /&gt;
	p = getpid();&lt;br /&gt;
	&lt;br /&gt;
	if (messages[sender].size() &amp;gt; 0 &amp;amp;&amp;amp; messages[sender].top() == num_receiver[sender]) {&lt;br /&gt;
		(msg, num_mess) = messages[sender].removeTop();&lt;br /&gt;
		num_receiver[sender]++;&lt;br /&gt;
		return msg;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	(msg, num_mess) = nfarecv(sender);&lt;br /&gt;
&lt;br /&gt;
	while (num_mess != num_receiver[sender]) {&lt;br /&gt;
		messages[sender].insert(msg, num_mess);&lt;br /&gt;
		(msg, num_mess) = nfarecv(sender);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	num_receiver[sender]++;&lt;br /&gt;
	return msg;	&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Soluzione proposta 2 (da controllare) ===&lt;br /&gt;
Proposta da [[User: SpookyWiki |SpookyWiki]] ([[User talk:SpookyWiki|talk]]) 18:42, 22 May 2023 (CEST)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
Map&amp;lt;&amp;lt;pid_t dest, pid_t mitt&amp;gt;, List&amp;lt;int&amp;gt; msgs&amp;gt; db;&lt;br /&gt;
&lt;br /&gt;
void asend(msg_t msg, pid_t dest) { //dobbiamo salvarci l'ordine&lt;br /&gt;
	pid_t mypid = getpid();&lt;br /&gt;
	int progressivo;&lt;br /&gt;
	if (db[&amp;lt;dest, mypid&amp;gt;] == null) {&lt;br /&gt;
		db.add(&amp;lt;dest, mypid&amp;gt;);&lt;br /&gt;
		db[&amp;lt;dest, mypid&amp;gt;].msgs.add(0)&lt;br /&gt;
		progressivo = 0;&lt;br /&gt;
	} else {&lt;br /&gt;
		progressivo = db[&amp;lt;dest, mypid&amp;gt;].msgs.getLast() +1;&lt;br /&gt;
		db[&amp;lt;dest, mypid&amp;gt;].msgs.add(progressivo);&lt;br /&gt;
	}&lt;br /&gt;
	nfasend(&amp;lt;msg, progressivo&amp;gt;, dest);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
msg_t arecv(pid_t sender) {&lt;br /&gt;
	pid_t mypid = getpid();&lt;br /&gt;
	int progressivo = db[&amp;lt;mypid, sender&amp;gt;].msgs[0];&lt;br /&gt;
	msg, prog = nfarecv(sender);&lt;br /&gt;
	while ( prog != progressivo) {&lt;br /&gt;
		nfasend(&amp;lt;msg, progressivo&amp;gt;, mypid);&lt;br /&gt;
		msg, prog = nfarecv(sender);&lt;br /&gt;
	}&lt;br /&gt;
	db[&amp;lt;mypid, sender&amp;gt;].msgs.remove(0);&lt;br /&gt;
	return msg;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Prova 2022/02/14 =&lt;br /&gt;
&lt;br /&gt;
== Esercizio c1 ==&lt;br /&gt;
Scrivere il monitor semdata che implementi un semaforo con dato. Questa astrazione prevede due operazioni:&lt;br /&gt;
&lt;br /&gt;
 datatype dP(void);&lt;br /&gt;
 void dV(datatype data);&lt;br /&gt;
&lt;br /&gt;
Non è previsto assegmento di valore iniziale nel costruttore, l'invariante è lo stesso dei semafori (con init = 0): ndP &amp;lt;=&lt;br /&gt;
ndV (dove ndP e ndV rappresentano rispettivamente il numero di operazioni dP e dV completate. I dati passati come&lt;br /&gt;
parametro alla dV devono essere memorizzati in ordine LIFO. L'operazione nP restituisce il valore più recente fra quelli&lt;br /&gt;
memorizzati (e lo cancella dalla struttura dati).&lt;br /&gt;
&lt;br /&gt;
=== Proposta di soluzione 1 ===&lt;br /&gt;
* Proposta da [[User:Flecart|Flecart]] ([[User talk:Flecart|talk]]) 12:06, 16 January 2023 (CET)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
class semdata {&lt;br /&gt;
&lt;br /&gt;
stack&amp;lt;datatype&amp;gt; pila;&lt;br /&gt;
condition p_waiting;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
semdata() {&lt;br /&gt;
	pila = stack();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
datatype dp(void) {&lt;br /&gt;
	if (pila.len() &amp;lt;= 0) {&lt;br /&gt;
		p_waiting.wait();&lt;br /&gt;
	}	&lt;br /&gt;
&lt;br /&gt;
	return pila.pop();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void dV(datatype data) {&lt;br /&gt;
	pila.push(data);&lt;br /&gt;
	p_waiting.signal();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Esercizio c2 ==&lt;br /&gt;
&lt;br /&gt;
Dato un servizio di message passing asincrono implementare un servizio di message passing sincrono&lt;br /&gt;
con selezione ordinata che ha la seguente interfaccia:&lt;br /&gt;
&lt;br /&gt;
 void snsend(msgtype msg, pid_t dest);&lt;br /&gt;
 msgtype snrecv(pid_t sender, int n);&lt;br /&gt;
&lt;br /&gt;
La funzione snrecv deve restituire l'n-mo messaggio proveniente dal mittente specificato (che può essere any). Se n ==&lt;br /&gt;
0 restituisce l'ultimo messaggio. Esempi:&lt;br /&gt;
m = snrecv(tizio, 1): restituisce il primo messaggio da tizio (attende se non ve ne sono)&lt;br /&gt;
m = snrecv(ANY, 42): restituisce il 42-mo messaggio da chiunque (attende se ci sono meno di 42 messaggi in attesa di&lt;br /&gt;
essere ricevuti)&lt;br /&gt;
m = snrecv(caio, 0): restituisce l'ultimo messaggio ricevuto da Caio (attende se non ci sono messaggi pendenti da Caio)&lt;br /&gt;
m = snrecv(ANY, 0): restituisce l'ultimo messaggio ricevuto, indipendentemente dal mittente.&lt;br /&gt;
&lt;br /&gt;
=== Proposta di soluzione 1 (da controllare)===&lt;br /&gt;
* Proposta da [[User:Barba|zBarba]] ([[User talk:Barba|talk]]) 10:54, 21 January 2024 (CET)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
// int db.count(pid_t sender): conta quanti messaggi inviati da sender sono presenti nel db. Se sender == ANY allora li conta tutti&lt;br /&gt;
// msg_t db.extract(pid_t sender,int  n): ritorna l'n-mo mesaggio del db inviato da sender. Se sender == ANY allora ritorna l'n-mo elemento&lt;br /&gt;
&lt;br /&gt;
void snsend(msgtype msg, pid_t dest){&lt;br /&gt;
    asend(&amp;lt;msg, getpid()&amp;gt;, dest)&lt;br /&gt;
    do{&lt;br /&gt;
        &amp;lt;m, snd&amp;gt; = arecv(dest)&lt;br /&gt;
        db.add(&amp;lt;m, snd&amp;gt;)&lt;br /&gt;
    }while(m != ACK)&lt;br /&gt;
    db.extract(dest, 0)&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
msgtype snrecv(pid_t sender, int n){&lt;br /&gt;
    if(n == 0){&lt;br /&gt;
        n = db.count(sender)&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    while(db.count(sender) &amp;lt; n){&lt;br /&gt;
        &amp;lt;m, snd&amp;gt; = arecv(sender)&lt;br /&gt;
        db.add(&amp;lt;m, snd&amp;gt;)&lt;br /&gt;
    }&lt;br /&gt;
    &amp;lt;m, snd&amp;gt; = db.extract(sender, n)&lt;br /&gt;
    asend(&amp;lt;ACK, getpid()&amp;gt;, snd)&lt;br /&gt;
    return m&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Prova 2022/01/17 =&lt;br /&gt;
&lt;br /&gt;
== Esercizio c1 ==&lt;br /&gt;
&lt;br /&gt;
Scrivere il monitor multibuf che implementi un buffer limitato (MAX elementi) di oggetti di tipo T che&lt;br /&gt;
implementi le seguenti procedure entry:&lt;br /&gt;
  void add(int n, T objexts[]);&lt;br /&gt;
  void get(int n, T objects[]);&lt;br /&gt;
La funzione add deve aggiungere al buffer gli n oggetti passati col parametro objects. La funzione get deve predere&lt;br /&gt;
dal buffer in modalità FIFO i primi n elementi presenti nel buffer e copiarli negli elementi del vettore objects.&lt;br /&gt;
Entrambe le funzioni devono attendere che vi siano le condizioni per poter essere completate: che ci siano n elementi&lt;br /&gt;
liberi per la add, che ci siano n elementi nel buffer per la get. Non sono ammesse esecuzioni parziali: mentre attendono&lt;br /&gt;
le rispettive condizioni nessun elemento può essere aggiunto o rimosso dal buffer.&lt;br /&gt;
La definizione del problema C.1 presenta casi di possibile deadlock?&lt;br /&gt;
&lt;br /&gt;
=== Soluzione proposta 1 ===&lt;br /&gt;
&lt;br /&gt;
* Proposta [[User:Flecart|Flecart]] ([[User talk:Flecart|talk]]) 12:41, 16 January 2023 (CET)&lt;br /&gt;
&lt;br /&gt;
Una situazione di deadlock è quando un add non ha abbastanza per inserire, e get non ha abbastanza da prendere. Se non utilizzo la coda come ho fatto così&lt;br /&gt;
rischio starvation.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
class multibuf {&lt;br /&gt;
	&lt;br /&gt;
T buffer[MAX];&lt;br /&gt;
int i, j;&lt;br /&gt;
int free;&lt;br /&gt;
queue&amp;lt;int,cond&amp;gt; add_queue;&lt;br /&gt;
&lt;br /&gt;
queue&amp;lt;int,cond&amp;gt; get_queue;&lt;br /&gt;
&lt;br /&gt;
multibuf {&lt;br /&gt;
	i = j = 0;&lt;br /&gt;
	free = MAX;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
void add(int n, T objects[]) {&lt;br /&gt;
	if (add_queue.size() &amp;gt; 0 || free &amp;lt; n) {&lt;br /&gt;
		condition c = new condition();&lt;br /&gt;
		add_queue.enqueue(n, c);&lt;br /&gt;
		c.wait();&lt;br /&gt;
		free(c);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	for (int k = j; k != (j + n) % MAX; k = (k + 1) % MAX) {&lt;br /&gt;
		int other_idx = (k - i) &amp;lt; 0 ? k + MAX - i : k - i;&lt;br /&gt;
		buffer[k] = objects[other_idx];&lt;br /&gt;
	}&lt;br /&gt;
	free -= n;&lt;br /&gt;
	j = (j + n) % MAX;&lt;br /&gt;
		&lt;br /&gt;
	while (get_queue.size() &amp;gt; 0 &amp;amp;&amp;amp; get_queue.front() &amp;lt;= MAX - free) {&lt;br /&gt;
		n, cond = get_queue.dequeue();&lt;br /&gt;
		cond.signal();&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void get(int n, T objects[]) {&lt;br /&gt;
	if (get_queue.size() &amp;gt; 0 || MAX - free &amp;lt; n) {&lt;br /&gt;
		condition c = new condition();&lt;br /&gt;
		get_queue.enqueue(n, c);&lt;br /&gt;
		c.wait();&lt;br /&gt;
		free(c);&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	for (int k = i; k != (i + n) % MAX; k = (k + 1) % MAX) {&lt;br /&gt;
		int other_idx = (k - i) &amp;lt; 0 ? k + MAX - i : k - i;&lt;br /&gt;
		objects[other_idx] = buffer[k];&lt;br /&gt;
	}&lt;br /&gt;
	free += n;&lt;br /&gt;
	i = (i + n) % MAX;&lt;br /&gt;
&lt;br /&gt;
	while (add_queue.size() &amp;gt; 0 &amp;amp;&amp;amp; add_queue.front() &amp;lt;= free) {&lt;br /&gt;
		n, cond = add_queue.dequeue();&lt;br /&gt;
		cond.signal();&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
} // multibuf&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Esercizio c2 ==&lt;br /&gt;
Un servizio di message passing sincrono senza selezione del mittente prevede una API con due funzioni:&lt;br /&gt;
  sasend(msg_t msg, pid dest);&lt;br /&gt;
  msg_t sarecv(void);&lt;br /&gt;
La funzione sarecv restituisce il primo messaggio ricevuto da qualsiasi mittente ed è bloccante se non ci sono&lt;br /&gt;
messaggi pendenti. la funzione sasend si blocca fino a quando il messaggio msg non viene ricevuto dal processo dest.&lt;br /&gt;
Dato quindi un servizio di message passing sincrono senza selezione del mittente implementare un servizio di&lt;br /&gt;
message passing sincrono (standard, quello definito nel corso) senza fare uso di processi server. &lt;br /&gt;
&lt;br /&gt;
=== Soluzione proposta 1 (da controllare) ===&lt;br /&gt;
* proposta da [[User:Flecart|Flecart]] ([[User talk:Flecart|talk]]) 18:25, 16 January 2023 (CET) &lt;br /&gt;
* Errore, ssend in questo caso non è sincrono, bisognerebbe uscire con l'ack dal receiver [[User:Flecart|Flecart]] ([[User talk:Flecart|talk]]) 22:56, 16 January 2023 (CET)&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
ssend(msg_t msg, pid dest) {&lt;br /&gt;
	sasend(&amp;lt;msg, getpid()&amp;gt;, dest);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// variabili interne di srecv&lt;br /&gt;
queue&amp;lt;msg_t&amp;gt; msgs[MAX_PROC];&lt;br /&gt;
&lt;br /&gt;
// suppongo non ci sia il caso in cui sender = ANY.&lt;br /&gt;
// nel caso ci fosse la necessità, si dovrebbe creare una altra struttura di dati&lt;br /&gt;
// che ordini globalmente il messaggio che sia arrivato prima.&lt;br /&gt;
msg_t srecv(pid sender) {&lt;br /&gt;
	if (msgs[sender].len() &amp;gt; 0) {&lt;br /&gt;
		return msgs[sender].dequeue();&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	while (true) {&lt;br /&gt;
		&amp;lt;msg, pid&amp;gt; = sarecv();&lt;br /&gt;
		if (pid == sender) {&lt;br /&gt;
			return msgs[pid].dequeue();&lt;br /&gt;
		} else {&lt;br /&gt;
			msgs[pid].enqueue(msg);&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Soluzione proposta 2 (da controllare) ===&lt;br /&gt;
&lt;br /&gt;
proposta da [[User:gio|Flecart Friend]] cedo la proprità intellettuale di questa soluzione a flecart&lt;br /&gt;
 &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
// mem è condivisa tra ssend e srecv di ogni processo&lt;br /&gt;
// essendo che un processo può solo mandare o ricevere alla volta&lt;br /&gt;
// non abbiamo bisogno di cs&lt;br /&gt;
&lt;br /&gt;
// inizializzati tutti a NULL&lt;br /&gt;
msg_t mem[MAXPID];&lt;br /&gt;
// in mem ci basta un messaggio per PID perchè un pid può aver mandato al&lt;br /&gt;
// massimo un messaggio essendo che sono bloccanti la send e la recive&lt;br /&gt;
&lt;br /&gt;
void ssend(msg_t msg, pid dest) {&lt;br /&gt;
  sasend(&amp;lt;getpid(),msg&amp;gt;,dest);&lt;br /&gt;
  while(true){&lt;br /&gt;
    &amp;lt;form_c,msg&amp;gt;=sarecv();&lt;br /&gt;
    // dovrebbe essere ovvio che se è from c allora il msg dovrebbe essere un&lt;br /&gt;
    // ack perchè se c avesse mandato un messaggio diverso vorrebbe dire che&lt;br /&gt;
    // sta facendo una send e se i due processi si fanno una send allora c'è&lt;br /&gt;
    // deadhlock&lt;br /&gt;
    if(from_c == dest &amp;amp;&amp;amp; msg == ACK){&lt;br /&gt;
      break;&lt;br /&gt;
    }else{&lt;br /&gt;
      mem[from_c]=msg;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
msg_t srecv(pid from) {&lt;br /&gt;
  if(mem[from]!=NULL){&lt;br /&gt;
    t=mem[from];&lt;br /&gt;
    mem[from]=NULL;&lt;br /&gt;
    ssend(ACK,from);&lt;br /&gt;
    return t;&lt;br /&gt;
  }&lt;br /&gt;
  while(true){&lt;br /&gt;
    &amp;lt;form_c,msg&amp;gt;=sarecv();&lt;br /&gt;
    if(from_c==from){&lt;br /&gt;
      ssend(ACK,from);&lt;br /&gt;
      return msg;&lt;br /&gt;
    }else{&lt;br /&gt;
      mem[from_c].push(msg);&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>Barba</name></author>
	</entry>
	<entry>
		<id>https://so.v2.cs.unibo.it/wiki/index.php?title=Prove_scritte_2021&amp;diff=3065</id>
		<title>Prove scritte 2021</title>
		<link rel="alternate" type="text/html" href="https://so.v2.cs.unibo.it/wiki/index.php?title=Prove_scritte_2021&amp;diff=3065"/>
		<updated>2024-01-20T13:47:35Z</updated>

		<summary type="html">&lt;p&gt;Barba: /* Consegna c1 */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
= Prova 21/07/2021=&lt;br /&gt;
&lt;br /&gt;
== Es C1 (da correggere) == &lt;br /&gt;
&lt;br /&gt;
Soluzione proposta da [https://so.v2.cs.unibo.it/wiki/index.php/User:Flecart Flecart friend],regalo a flecart la proprietà intellettuale di questa soluzione&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
&lt;br /&gt;
class node{&lt;br /&gt;
  node parent;&lt;br /&gt;
  sq sq1;&lt;br /&gt;
  cond c;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
class BinTree{&lt;br /&gt;
  vector&amp;lt;node&amp;gt; base;&lt;br /&gt;
  void create(int N){&lt;br /&gt;
    base=new vector&amp;lt;node&amp;gt;(2^N);&lt;br /&gt;
    for(int i=0;i&amp;lt;2^N;i++)&lt;br /&gt;
      base[i]=new node(null,0,new cond);&lt;br /&gt;
    for(int i=1;i&amp;lt;=N;i++){&lt;br /&gt;
      for(int j=0;j&amp;lt;2^(N-i);j++){&lt;br /&gt;
        get(j,i-1).parent=get(j+i,i-1).parent=new node(null,0,new cond);&lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
  node get(int i,int level){&lt;br /&gt;
    return get(base[i],level);&lt;br /&gt;
  }&lt;br /&gt;
  node get(node n,int level){&lt;br /&gt;
    if(level==0){&lt;br /&gt;
      return node;&lt;br /&gt;
    }&lt;br /&gt;
    return get(node.parent,level-1);&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
class Torneo{&lt;br /&gt;
  BinTree bin(N);&lt;br /&gt;
  int forma[2^N];&lt;br /&gt;
  bool win;&lt;br /&gt;
&lt;br /&gt;
  bool gioca(int i,int turno,int forma){&lt;br /&gt;
    forma[i]=forma;&lt;br /&gt;
    if null==bin.get(i,turno).sq1{&lt;br /&gt;
      bin.get(i,turno).sq1=i;&lt;br /&gt;
      bin.get(i,turno).c.wait();&lt;br /&gt;
      return !win;&lt;br /&gt;
    }else{&lt;br /&gt;
      sq1= bin.get(i,turno).sq1;&lt;br /&gt;
      if(forma[sq1]==forma[i]){&lt;br /&gt;
        win=random();&lt;br /&gt;
      }else{&lt;br /&gt;
        win=forma[sq1]&amp;lt;forma[i];&lt;br /&gt;
      }&lt;br /&gt;
      bin.get(i,turno).signal();&lt;br /&gt;
    }&lt;br /&gt;
    return win;&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Es G1  == &lt;br /&gt;
=== consegna ===&lt;br /&gt;
&lt;br /&gt;
Sia dato l'algoritmo di rimpiazzamento modulo che data una memoria di NF frame , se avviene un page&lt;br /&gt;
fault in corrispondenza dell'i-mo elemento della stringa di riferimenti modulo sceglie come pagina vittima quella che&lt;br /&gt;
occupa il frame i % NF.&lt;br /&gt;
Es. se NF fosse 3, la prima pagina viene messa nel frame 1 perché 1 % 3 = 1, se l'undicesimo elemento della stringa&lt;br /&gt;
causa un page fault, si elimina la pagina nel frame 2 (11 % 3 = 2).&lt;br /&gt;
A) Considerare la stringa di riferimenti seguente e mostrare il funzionamento di modulo nei casi NF = 3 e NF = 4:&lt;br /&gt;
1 2 3 4 5 3 3 3 1 5&lt;br /&gt;
B) modulo è un algoritmo a stack?&lt;br /&gt;
&lt;br /&gt;
=== Soluzione proposta (da controllare) === &lt;br /&gt;
[[User:Flecart|Flecart]] ([[User talk:Flecart|talk]]) 14:44, 4 May 2023 (CEST)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Caso in cui NF=3&lt;br /&gt;
allora&lt;br /&gt;
1 X X   1&lt;br /&gt;
1 2 X   2&lt;br /&gt;
1 2 3   3&lt;br /&gt;
4 2 3   4&lt;br /&gt;
4 5 3   5&lt;br /&gt;
4 5 3   3&lt;br /&gt;
4 5 3   3&lt;br /&gt;
4 5 3   3&lt;br /&gt;
1 5 3   1&lt;br /&gt;
1 5 3   5&lt;br /&gt;
&lt;br /&gt;
Caso in cui NF=4&lt;br /&gt;
1 X X X 1&lt;br /&gt;
1 2 X X 2&lt;br /&gt;
1 2 3 X 3&lt;br /&gt;
1 2 3 4 4&lt;br /&gt;
5 2 3 4 5&lt;br /&gt;
5 2 3 4 3&lt;br /&gt;
5 2 3 4 3&lt;br /&gt;
5 2 3 4 3&lt;br /&gt;
1 2 3 4 1&lt;br /&gt;
5 2 3 4 5&lt;br /&gt;
&lt;br /&gt;
Allora, l'algoritmo non è a stack perché nella penultima accesso al frame ho nel caso NF=3 che&lt;br /&gt;
{1, 5, 3}, ma questo non è contenuto in {1, 2, 3, 4}.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Prova 2021/09/15 =&lt;br /&gt;
&lt;br /&gt;
== Esercizio C1 == &lt;br /&gt;
&lt;br /&gt;
=== Consegna === &lt;br /&gt;
Esercizio c.1: Scrivere il monitor alrv (at least rendez-vous) che fornisce una sola procedure entry:&lt;br /&gt;
procedure entry void at_least(int n)&lt;br /&gt;
Quando un processo chiama la funzione at_least vuol dire che vuole sincronizzarsi con un insieme di almeno n&lt;br /&gt;
processi (incluso il chiamante).&lt;br /&gt;
Esempi:&lt;br /&gt;
Se un processo chiama at_least(1) non si blocca.&lt;br /&gt;
Se il processo p chiama at_least(2) si blocca, se poi il processo q chiama at_least(2) oppure at_least(1) si&lt;br /&gt;
sbloccano sia p sia q (la richiesta di p è soddisfatta, ne aspettava almeno 2, p e q)&lt;br /&gt;
Se il processo p chiama at_least(2) si blocca, se poi il processo q chiama at_least(3) si blocca anch'esso perché&lt;br /&gt;
sebbene la richiesta di p possa essere soddisfatta, q non può ancora sbloccarsi: ci sono solo 2 processi in attesa mentre&lt;br /&gt;
q ne vuole 3. Un terzo processo che chiami at_least(x) con x=1,2,3 li sblocca tutti.&lt;br /&gt;
Hint: sia w[k ] il numero dei processi in attesa di essere in almeno k (quelli che hanno chiamato at_least(k) e non&lt;br /&gt;
hanno completato l'esecuzione della funzione). Sia s[n]=∑&lt;br /&gt;
k=1&lt;br /&gt;
n&lt;br /&gt;
w[k ] (rappresenta il numero di processi soddisfacibili:&lt;br /&gt;
e.g. se ci sono 4 processi in attesa, potrebbero essere soddisfatte le richieste dei processi che ne aspettano almeno 2,&lt;br /&gt;
almeno 3 o almeno 4). Preso, se esiste, il massimo indice m tale che s[m]≥m tutti i processi in attesa di essere in n,&lt;br /&gt;
per n≤m possono essere sbloccati.&lt;br /&gt;
&lt;br /&gt;
=== 1. Soluzione proposta ===&lt;br /&gt;
Soluzione proposta da [https://so.v2.cs.unibo.it/wiki/index.php/User:Flecart Flecart]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
&lt;br /&gt;
extern int MAX;  // il massimo numero di attesa&lt;br /&gt;
monitor alrv {&lt;br /&gt;
	int w[MAX];&lt;br /&gt;
	int s[MAX];&lt;br /&gt;
	condition c[MAX];&lt;br /&gt;
&lt;br /&gt;
	init() {&lt;br /&gt;
		for (int i = 0; i &amp;lt; MAX; i++) {&lt;br /&gt;
			w[i] = s[i] = 0;&lt;br /&gt;
		}&lt;br /&gt;
	}	&lt;br /&gt;
&lt;br /&gt;
procedure entry void at_least(int n) {&lt;br /&gt;
	if (n &amp;gt;= MAX || n &amp;lt;= 0) raise error;&lt;br /&gt;
	&lt;br /&gt;
	int i;&lt;br /&gt;
	for (i = n; i &amp;lt; MAX; i++) s[i]++;&lt;br /&gt;
	&lt;br /&gt;
	for (i = MAX - 1; i &amp;gt; 0; i--) {&lt;br /&gt;
		if (s[i] &amp;gt;= i) break;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	if (i &amp;gt; 0) {&lt;br /&gt;
		for (int j = 0; j &amp;lt;= i; j++) {&lt;br /&gt;
			while (w[j] &amp;gt; 0) {&lt;br /&gt;
				c[j].signal();&lt;br /&gt;
				w[j]--;&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
		&lt;br /&gt;
		s[0] = 0;&lt;br /&gt;
		for (int i = 1; i &amp;lt; MAX; i++) {&lt;br /&gt;
			s[i] = w[i] + s[i - 1];&lt;br /&gt;
		}&lt;br /&gt;
	} else {&lt;br /&gt;
		w[n]++;&lt;br /&gt;
		c[n].wait();&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== 2. Soluzione proposta ===&lt;br /&gt;
Soluzione proposta da [https://so.v2.cs.unibo.it/wiki/index.php/User:Flecart Flecart friend],regalo a flecart la proprietà intellettuale di questa soluzione&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
&lt;br /&gt;
class Monitor{&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
  min_heap&amp;lt;(int,cond)&amp;gt; h;&lt;br /&gt;
&lt;br /&gt;
  void at_least(int n){&lt;br /&gt;
    int sum=0;&lt;br /&gt;
    int max_to_sblock= -INF;&lt;br /&gt;
    cond c = new cond(n);&lt;br /&gt;
    h.push((n,c));&lt;br /&gt;
    // la heap viene visitata in maniera crescente&lt;br /&gt;
    for(auto f=h.begin_iter();null!=f.next();f++) {&lt;br /&gt;
        sum++;&lt;br /&gt;
        if(f.0&amp;lt;=sum){&lt;br /&gt;
          max_to_sblock =f.0;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    for(auto f=h.begin_iter();null!=f.next();f++) {&lt;br /&gt;
        if(f.0&amp;lt;=max_to_sblock){&lt;br /&gt;
          f.1.signal();&lt;br /&gt;
          h.remove(c);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    if(n&amp;gt;max_to_sblock){&lt;br /&gt;
      c.wait();&lt;br /&gt;
    }&lt;br /&gt;
    free(c)&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
=== Soluzione proposta 3 (da controllare) ===&lt;br /&gt;
Proposta da [[User:SpookyWiki|SpookyWiki]] ([[User talk:SpookyWiki|talk]]) 11:41, 25 May 2023 (CEST)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
monitor alrv {&lt;br /&gt;
	int maxindex;&lt;br /&gt;
	Map&amp;lt;int, int&amp;gt; waiting4[];&lt;br /&gt;
	Map&amp;lt;int, condition&amp;gt; ok2go[]&lt;br /&gt;
&lt;br /&gt;
	alrv() {&lt;br /&gt;
		maxindex = 0;&lt;br /&gt;
		waiting4 = new Map&amp;lt;int, int&amp;gt;();&lt;br /&gt;
		ok2go = new Map&amp;lt;int, condition&amp;gt;();&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	procedure int check() { //procedura che controlla che i processi in attesa fino n possano essere sbloccati o meno&lt;br /&gt;
		int sum = 0;&lt;br /&gt;
		int m = 0;&lt;br /&gt;
		do {&lt;br /&gt;
			m++&lt;br /&gt;
			sum += waiting4[m];&lt;br /&gt;
		} while(m &amp;lt; maxindex &amp;amp;&amp;amp; sum &amp;gt;= m)&lt;br /&gt;
		return sum &amp;gt;= m ? m : m - 1;&lt;br /&gt;
	} &lt;br /&gt;
&lt;br /&gt;
	procedure entry void at_least(int n) {&lt;br /&gt;
		if(waiting4[n] == null) {&lt;br /&gt;
			waiting4.add(n);&lt;br /&gt;
			waiting4[n]++;&lt;br /&gt;
			ok2.add(n);&lt;br /&gt;
		}&lt;br /&gt;
		if (n &amp;gt; maxindex)&lt;br /&gt;
			maxindex = n;&lt;br /&gt;
		int m;&lt;br /&gt;
		if ((m = check(n)) &amp;gt; 0) {&lt;br /&gt;
			for(int i = 1; i &amp;lt;= m; i++) {&lt;br /&gt;
				ok2[i].signal();&lt;br /&gt;
				waiting4[i] = 0;&lt;br /&gt;
			}&lt;br /&gt;
		} else {&lt;br /&gt;
			ok2go[n].wait();&lt;br /&gt;
			ok2go[n].signal();&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Esercizio C2 == &lt;br /&gt;
Dato un servizio di message passing sincrono scrivere, senza fare uso di processi server, un servizio di&lt;br /&gt;
message passing sincrono concatenato che abbia le seguenti primitive:&lt;br /&gt;
  void chained_send (T msg, list_of_pids dests)&lt;br /&gt;
  T chained_recv(void)&lt;br /&gt;
La funzione chained_send deve fare in modo che tutti i processi indicati nella lista dests ricevano il messaggio. Il&lt;br /&gt;
processo che chiama la chained_send si blocca solo fino a quando il primo processo della lista dests non chiama una&lt;br /&gt;
chained_recv, il primo si sblocca quando il secondo chiama la chained_recv e così via.&lt;br /&gt;
( la funzione chained_recv riceve messaggi provenienti da qualsiasi mittente)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Soluzione proposta 1 (da controllare) ===&lt;br /&gt;
* proposta da [[User:Flecart|Flecart]] ([[User talk:Flecart|talk]]) 18:37, 16 January 2023 (CET)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
void chained_send(T msg, list_of_pids dests) {&lt;br /&gt;
	if (dests.len() &amp;lt; 1) return ERROR;&lt;br /&gt;
	else if (dests.len() == 1) {&lt;br /&gt;
		pid head = dests[0];&lt;br /&gt;
		ssend(&amp;lt;msg, NULL&amp;gt;, head);&lt;br /&gt;
	} else {&lt;br /&gt;
		&amp;lt;head, rest&amp;gt; = dests[0], dests[1:];&lt;br /&gt;
		ssend(&amp;lt;msg, rest&amp;gt;, head);&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
T chained_recv(void) {&lt;br /&gt;
	&amp;lt;msg, rest&amp;gt; = srecv(ANY);&lt;br /&gt;
	if (rest == NULL) return msg;&lt;br /&gt;
&lt;br /&gt;
	if (rest.len() == 1) {&lt;br /&gt;
		pid head = rest[0];&lt;br /&gt;
		ssend(&amp;lt;msg, NULL&amp;gt;, head);&lt;br /&gt;
	} else if (rest.len() &amp;gt; 1) {&lt;br /&gt;
		&amp;lt;head, rest2&amp;gt; = rest[0], rest[1:];&lt;br /&gt;
		ssend(&amp;lt;msg, rest2&amp;gt;, head);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	return msg;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Soluzione proposta 2 (da controllare) ===&lt;br /&gt;
Proposta da [[User:SpookyWiki|SpookyWiki]] ([[User talk:SpookyWiki|talk]]) 12:20, 23 May 2023 (CEST)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
void chained_send(T msg, list_of_pids dests) {&lt;br /&gt;
	if ( dests.length() &amp;lt; 1)&lt;br /&gt;
		return;&lt;br /&gt;
	pid_t dest = dests.pop(0); //rimuovo e prendo il primo destinatario&lt;br /&gt;
	ssend(&amp;lt;msg, dests&amp;gt;, dest);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
T chained_recv(void) {&lt;br /&gt;
	&amp;lt;msg, dests&amp;gt; == srecv(ANY);&lt;br /&gt;
	if(dests.length() &amp;gt; 0) { //il messaggio deve essere ancora inviato ad altri&lt;br /&gt;
		pid_t dest = dests.pop(0);&lt;br /&gt;
		ssend(&amp;lt;msg, dests&amp;gt;, dest);&lt;br /&gt;
	}&lt;br /&gt;
	return msg;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Prova 2021/06/23 =&lt;br /&gt;
&lt;br /&gt;
== Esercizio C1 == &lt;br /&gt;
&lt;br /&gt;
=== Consegna === &lt;br /&gt;
Esercizio c.1: Scrivere il monitor delayvalue con una sola procedure entry:&lt;br /&gt;
  int delay(int value);&lt;br /&gt;
Il monitor deve sospendere i primi NDELAY processi che chiamano la delay. Le successive chiamate di delay&lt;br /&gt;
devono mantenere costante il numero di processi sospesi, ogni successiva chiamata devo riattivare il primo&lt;br /&gt;
processo in attesa prima di sospendersi, la delay ritorna il valore passato come parametro dal processo che&lt;br /&gt;
ne ha riattivato l'esecuzione. e.g. se NDELAY è 2:&lt;br /&gt;
  P1: delay(44) -&amp;gt; P1 si sospende&lt;br /&gt;
  P2: delay(40) -&amp;gt; P2 si sospende&lt;br /&gt;
  P3: delay(42) -&amp;gt; P1 si riattiva e ritorna 42, P3 si sospende&lt;br /&gt;
  P4: delay(22) -&amp;gt; P2 si riattiva e ritorna 22, P4 si sospende&lt;br /&gt;
&lt;br /&gt;
=== Soluzione proposta 1 ===&lt;br /&gt;
Soluzione proposta da [https://so.v2.cs.unibo.it/wiki/index.php/User:Flecart Flecart]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
&lt;br /&gt;
// variabile definita altrove.&lt;br /&gt;
extern int NDELAY;&lt;br /&gt;
&lt;br /&gt;
class Monitor {&lt;br /&gt;
    Queue&amp;lt;condition&amp;gt; stopped;&lt;br /&gt;
    int curr_value;&lt;br /&gt;
    Monitor {&lt;br /&gt;
        stopped = Queue&amp;lt;condition&amp;gt;();&lt;br /&gt;
        curr_value = 0;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    int delay(int value) {&lt;br /&gt;
        curr_value = value;&lt;br /&gt;
        if (stopped.size() == NDELAY) {&lt;br /&gt;
            condition first = stopped.dequeue();&lt;br /&gt;
            first.signal();&lt;br /&gt;
        }&lt;br /&gt;
        condition c = new condition();&lt;br /&gt;
        stopped.enqueue(c);&lt;br /&gt;
        c.wait();    &lt;br /&gt;
        free(c);&lt;br /&gt;
&lt;br /&gt;
        return curr_value;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Soluzione proposta 2 ===&lt;br /&gt;
Soluzione proposta da [https://so.v2.cs.unibo.it/wiki/index.php/User:Flecart Flecart friend], regalo la proprietà intellettuale a flecart. &lt;br /&gt;
&lt;br /&gt;
* Controllato da [[User:Flecart|Flecart]] ([[User talk:Flecart|talk]]) 18:10, 16 January 2023 (CET), corretto se si assume la FIFO interna della condition.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
&lt;br /&gt;
monitor dalayvalue{&lt;br /&gt;
&lt;br /&gt;
#define NDELAY 22&lt;br /&gt;
  int blocked=0;&lt;br /&gt;
  int lastvalue=0;&lt;br /&gt;
  cond c;&lt;br /&gt;
&lt;br /&gt;
  int dalay(int value){&lt;br /&gt;
    lastvalue=value;&lt;br /&gt;
    if(blocked&amp;lt;NDELAY){&lt;br /&gt;
      blocked++;&lt;br /&gt;
      c.wait();&lt;br /&gt;
    }else if(blocked==NDELAY){&lt;br /&gt;
      c.signal();&lt;br /&gt;
      c.wait();&lt;br /&gt;
    }&lt;br /&gt;
    return lastvalue;&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Soluzione proposta 3 (da controllare) ===&lt;br /&gt;
Proposta da [[User:SpookyWiki|SpookyWiki]] ([[User talk:SpookyWiki|talk]]) 12:05, 25 May 2023 (CEST)&lt;br /&gt;
&lt;br /&gt;
Si assume una politica FIFO delle condition, NDELAY non variabile d'ambiente ma parametro passato all'inizializzazione.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
monitor delayvalue {&lt;br /&gt;
	int ndelay;&lt;br /&gt;
	int in;&lt;br /&gt;
	int lastvalue;&lt;br /&gt;
	condition ok2return;&lt;br /&gt;
&lt;br /&gt;
	delay(int NDELAY) {&lt;br /&gt;
		ndelay = NDELAY;&lt;br /&gt;
		in = 0;&lt;br /&gt;
		lastvalue = 0;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	procedure entry int delay(int value) {&lt;br /&gt;
		if (in &amp;gt;= ndelay) {&lt;br /&gt;
			lastvalue = value;&lt;br /&gt;
			ok2return.signal();&lt;br /&gt;
		} else &lt;br /&gt;
			in++;&lt;br /&gt;
		ok2return.wait();&lt;br /&gt;
		return lastvalue;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Esercizio c2 ==&lt;br /&gt;
Implementare usando semafori ordinari (fair, fifo) un servizio di semafori a priorità lifo che&lt;br /&gt;
fornisca le seguenti primitive:&lt;br /&gt;
 void PLP(int prio);&lt;br /&gt;
 void PLV()&lt;br /&gt;
PLP e PLV si devono comportare rispettivamente come P e V. Quando la PLV deve riattivare un processo&lt;br /&gt;
sceglie fra quelli in attesa quello a priorità massima, nel caso siano presenti più processi a priorità massima&lt;br /&gt;
sceglie quello in attesa da meno tempo. &lt;br /&gt;
&lt;br /&gt;
=== Soluzione proposta 1 ===&lt;br /&gt;
&lt;br /&gt;
Esercizio c2  da Flecart.&lt;br /&gt;
&lt;br /&gt;
controllato:&lt;br /&gt;
* [[User:Gio|Gio]] ([[User talk:Gio|talk]]) 17:45, 16 January 2023 (CET)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Stack&amp;lt;semaphore&amp;gt; stack[MAX_PRIORITY];&lt;br /&gt;
int num_V = 0;&lt;br /&gt;
semaphore mutex(1);&lt;br /&gt;
&lt;br /&gt;
void  PLP(int prio) {&lt;br /&gt;
    mutex.P();&lt;br /&gt;
    if (num_V &amp;gt; 0) {&lt;br /&gt;
        num_V--;&lt;br /&gt;
        mutex.V();&lt;br /&gt;
        return;&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    semaphore sem = semaphore(0);&lt;br /&gt;
    stack[prio].push(sem);&lt;br /&gt;
    mutex.V();&lt;br /&gt;
    sem.P();&lt;br /&gt;
&lt;br /&gt;
    mutex.V();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
void PLV() {&lt;br /&gt;
    mutex.P();&lt;br /&gt;
    &lt;br /&gt;
    for (int i = MAX_PRIORITY - 1; i &amp;gt;= 0; i--) {&lt;br /&gt;
        if (stack[i].size() &amp;gt; 0) {&lt;br /&gt;
            sem = stack[i].pop();&lt;br /&gt;
            sem.V();&lt;br /&gt;
            return;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    num_V++;&lt;br /&gt;
&lt;br /&gt;
    mutex.V();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Prova 2021/05/26 =&lt;br /&gt;
&lt;br /&gt;
== Consegna c1 == &lt;br /&gt;
&lt;br /&gt;
Esercizio c.1: Un buffer sincrono strampalato (bss) ha due procedure entry:&lt;br /&gt;
void put(T value)&lt;br /&gt;
list of T get(void)&lt;br /&gt;
La entry put viene utilizzata per aggiungere un elemento e la entry get per leggere tutti quelli disponibili.&lt;br /&gt;
Se più processi chiamano la put quando nessun processo è in attesa per una get, rimangono tutti bloccati.&lt;br /&gt;
Quando successivamente un processo chiama la get riceve la lista di tutti gli elementi inseriti con le put e&lt;br /&gt;
tutti i processi vengono sbloccati.&lt;br /&gt;
Se il buffer è vuoto tutti i processi che chiamano la get rimangono bloccati. quando un processo chiama&lt;br /&gt;
successivamente la put tutti i processi in attesa per la get si sbloccano e ricevono lo stesso valore di ritorno:&lt;br /&gt;
una lista contenente il solo valore passato come parametro alla put. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Soluzione proposta 1 ===&lt;br /&gt;
&lt;br /&gt;
Soluzione proposta da [https://so.v2.cs.unibo.it/wiki/index.php/User:Flecart Flecart]&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
int num = 0; // se è positiva rappresenta numero di gets che aspettano, se negativa, numero di puts&lt;br /&gt;
semaphore semput(0);&lt;br /&gt;
semaphore semget(0);&lt;br /&gt;
semaphore mutex(1);&lt;br /&gt;
list&amp;lt;T&amp;gt; global_list;&lt;br /&gt;
&lt;br /&gt;
void put(T value) {&lt;br /&gt;
    //&amp;lt; await(num &amp;gt; 0) --&amp;gt; global_list.add(value) &amp;gt;&lt;br /&gt;
    mutex.P();&lt;br /&gt;
    if (num &amp;lt;= 0) {&lt;br /&gt;
        num--;&lt;br /&gt;
        mutex.V();&lt;br /&gt;
        semput.P();&lt;br /&gt;
        num++;&lt;br /&gt;
    }&lt;br /&gt;
    global_list.add(value);&lt;br /&gt;
&lt;br /&gt;
    if (num &amp;lt; 0)&lt;br /&gt;
        semput.V();&lt;br /&gt;
    else &lt;br /&gt;
        semget.V();&lt;br /&gt;
&lt;br /&gt;
    return;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
list of T get() {&lt;br /&gt;
    list&amp;lt;T&amp;gt; local_list;&lt;br /&gt;
&lt;br /&gt;
    mutex.P();&lt;br /&gt;
    if (num &amp;gt;= 0) {&lt;br /&gt;
        num++;&lt;br /&gt;
        mutex.V();&lt;br /&gt;
        semget.P();&lt;br /&gt;
        num--;&lt;br /&gt;
    } else {&lt;br /&gt;
        semput.V();&lt;br /&gt;
        semget.P();&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    local_list = global_list; // fa deep copy&lt;br /&gt;
&lt;br /&gt;
    if (num &amp;gt; 0) {&lt;br /&gt;
        semget.V();&lt;br /&gt;
    } else {&lt;br /&gt;
        global_list = list&amp;lt;T&amp;gt;();&lt;br /&gt;
        mutex.V(); &lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    return local_list;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Soluzione proposta 2 ===&lt;br /&gt;
&lt;br /&gt;
Soluzione proposta da [https://so.v2.cs.unibo.it/wiki/index.php/User:Gio Gio]&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
class bss{&lt;br /&gt;
  int waiting_put=0;&lt;br /&gt;
  int waiting_get=0;&lt;br /&gt;
  cond cw,cg;&lt;br /&gt;
  queue&amp;lt;T&amp;gt; q;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
  void put(T value){&lt;br /&gt;
    q.push(T);&lt;br /&gt;
    if(waiting_get&amp;gt;0){&lt;br /&gt;
      cg.signal()&lt;br /&gt;
    }else{&lt;br /&gt;
      waiting_put++;&lt;br /&gt;
      cw.wait();&lt;br /&gt;
      waiting_put--;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  list&amp;lt;T&amp;gt; get(){&lt;br /&gt;
    if(waiting_put&amp;gt;0){&lt;br /&gt;
      while(waiting_put&amp;gt;0){&lt;br /&gt;
        cw.signal();&lt;br /&gt;
      }&lt;br /&gt;
    }else{&lt;br /&gt;
      waiting_get++;&lt;br /&gt;
      cg.wait();&lt;br /&gt;
      waiting_get--;&lt;br /&gt;
    }&lt;br /&gt;
    list&amp;lt;T&amp;gt; p= q.tolist();&lt;br /&gt;
    if(waiting_get&amp;gt;0){&lt;br /&gt;
      cg.signal();&lt;br /&gt;
    }&lt;br /&gt;
    q.removeAll();&lt;br /&gt;
    return p;&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Soluzione proposta 3 ===&lt;br /&gt;
&lt;br /&gt;
Soluzione proposta da [[User:Barba|zBarba]] ([[User talk:Barba|talk]]) 14:47, 20 January 2024 (CET)&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
monitor bss:&lt;br /&gt;
list&amp;lt;T&amp;gt; buffer&lt;br /&gt;
int nget&lt;br /&gt;
condition ok2put&lt;br /&gt;
condition ok2get&lt;br /&gt;
&lt;br /&gt;
procedure entry void put(T value){&lt;br /&gt;
    buffer.add(value)&lt;br /&gt;
    if(nget==0){&lt;br /&gt;
        ok2put.wait()&lt;br /&gt;
        ok2put.signal() //cascata di signal&lt;br /&gt;
    }else if(nget&amp;gt;0){&lt;br /&gt;
        ok2get.signal()&lt;br /&gt;
        buffer.clear()&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
procedure entry list&amp;lt;T&amp;gt; get(void){&lt;br /&gt;
    ok2put.signal()&lt;br /&gt;
    if(buffer.isEmpty()){&lt;br /&gt;
        nget++&lt;br /&gt;
        ok2get.wait()&lt;br /&gt;
        ok2get.signal() //cascata di signal&lt;br /&gt;
        nget--&lt;br /&gt;
    }&lt;br /&gt;
    return buffer&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== esercizio c2 == &lt;br /&gt;
&lt;br /&gt;
Dato un servizio di message passing asincrono implementare un servizio di message passing&lt;br /&gt;
asincrono a selezione di mittenti (samp) senza fare uso di processi server.&lt;br /&gt;
Il servizio samp ha due primitive:&lt;br /&gt;
sasend(message , destination)&lt;br /&gt;
sarecv(senders)&lt;br /&gt;
dove senders è un insieme.&lt;br /&gt;
la sarecv restituisce il primo messaggio che uno dei processi in senders ha spedito al processo ricevente&lt;br /&gt;
usando la sasend (o spedito da qualsiasi processo se senders è vuoto).&lt;br /&gt;
&lt;br /&gt;
=== Soluzione proposta 1 === &lt;br /&gt;
&lt;br /&gt;
Soluzione proposta da [[User:Flecart|Flecart]] ([[User talk:Flecart|talk]]) 15:29, 15 January 2023 (CET)&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
sasend(message, destination) {&lt;br /&gt;
	pid t = getpid();&lt;br /&gt;
	asend(&amp;lt;message, t&amp;gt;, destination);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// variabile privata di sarecv&lt;br /&gt;
queue all_messages[MAX_PROC];&lt;br /&gt;
&lt;br /&gt;
// stora tutti i messaggi ricevuti, lo utilizziamo come queue per tutti, con &lt;br /&gt;
// anche la possibilità di rimuovere in un punto a scelta.&lt;br /&gt;
vector&amp;lt;&amp;lt;messages, pid&amp;gt;&amp;gt; msg; &lt;br /&gt;
sarecv(senders) {&lt;br /&gt;
	if (senders.len() == 0) {&lt;br /&gt;
		if (msg.len() == 0) {&lt;br /&gt;
			&amp;lt;message, sender&amp;gt; = arecv(ANY);&lt;br /&gt;
			return message;&lt;br /&gt;
		} else {&lt;br /&gt;
			&amp;lt;message, sender&amp;gt; = msg.pop_back();&lt;br /&gt;
			return message;&lt;br /&gt;
		}&lt;br /&gt;
	} else {&lt;br /&gt;
		do {&lt;br /&gt;
			for (idx in senders) {&lt;br /&gt;
				if (all_messages[idx].size() &amp;gt; 0) {&lt;br /&gt;
					message = all_messages[idx].dequeue();&lt;br /&gt;
					// rimuove il singolo messaggio dal vector, non tutti quelli uguali.&lt;br /&gt;
					msg.remove(&amp;lt;message, idx&amp;gt;);&lt;br /&gt;
					return message;&lt;br /&gt;
				}&lt;br /&gt;
			}	&lt;br /&gt;
			&lt;br /&gt;
			&amp;lt;message, sender&amp;gt; = arecv(ANY);&lt;br /&gt;
			msg.push_back(&amp;lt;message, sender&amp;gt;);&lt;br /&gt;
			all_messages[sender].enqueue(&amp;lt;message&amp;gt;);&lt;br /&gt;
		} while(true);&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Soluzione proposta 2 === &lt;br /&gt;
&lt;br /&gt;
Soluzione proposta da [[User:Flecart|Flecart]] ([[User talk:Flecart|talk]]) 13:05, 7 March 2023 (CET)&lt;br /&gt;
dovrebbe essere più semplice della precedente.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
sasend(message, destination) {&lt;br /&gt;
	pid t = getpid();&lt;br /&gt;
	asend(&amp;lt;message, t&amp;gt;, destination);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
extern int MAX_PID;&lt;br /&gt;
&lt;br /&gt;
// storerà tutti i messaggi che ricevo che non riesco a utilizzare subito&lt;br /&gt;
queue&amp;lt;message&amp;gt; msgs[MAX_PID];&lt;br /&gt;
sarecv(senders) {&lt;br /&gt;
	if (senders == NULL) {&lt;br /&gt;
		senders = {0, 1, ..., MAX_PID};&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	for (pid_t sender : senders) {&lt;br /&gt;
		if (msgs[sender].size() &amp;gt; 0) {&lt;br /&gt;
			message_t msg = msgs[sender].dequeue();&lt;br /&gt;
			return msg;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	while (True) {&lt;br /&gt;
		msg, pid = arecv(ANY);&lt;br /&gt;
		if (pid in senders) {&lt;br /&gt;
			return msg;&lt;br /&gt;
		} else {&lt;br /&gt;
			msgs[pid].enqueue(msg);&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>Barba</name></author>
	</entry>
	<entry>
		<id>https://so.v2.cs.unibo.it/wiki/index.php?title=User:Barba&amp;diff=3064</id>
		<title>User:Barba</title>
		<link rel="alternate" type="text/html" href="https://so.v2.cs.unibo.it/wiki/index.php?title=User:Barba&amp;diff=3064"/>
		<updated>2024-01-20T13:42:18Z</updated>

		<summary type="html">&lt;p&gt;Barba: Created page with &amp;quot;Marco Reina&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Marco Reina&lt;/div&gt;</summary>
		<author><name>Barba</name></author>
	</entry>
</feed>