Ponte Tibetano 1
// L'algoritmo dovrebbe esser corretto, sono tuttavia convinto che ci sia un'anomalia nel controllo del peso.
// A mio parere sorge dall'utilizzo di un HANDLE temporaneo che ad ogni ciclo viene sovrascritto!
// Tento di risolvere...inserendo il controllo Peso dopo la creazione di ogni singolo Thread.
// A volte il programma sembra vada in deadlock...penso sia legato ai timeout...cmq...il 90% delle volte funziona.
#include <conio.h>
#include <ctype.h>
#include <time.h>
#include <windows.h>
#include <stdio.h>
#include <process.h>
#define MAXPESO 1000 // Peso massimo sostenibile dal ponte
#define PESOP 150 // Peso di una persona Standard
#define PESOC 300 // Peso di un carro Standard
#define ANDATA 0 // ANDATA
#define RITORNO 1 // RITORNO
#define GetRandom(min, max) ((rand() % (int)(((max) +1) - (min))) + (min)) // Funzione di Generazione interi casuali
// Le seguenti variabili globali saranno protette da Mutex!
int PesoAttuale =
0;
// Var. Glob. per il Peso Attuale sul ponte
int Persone
[2] =
{0,
0};
// Var. Glob. per il Conteggio Persone sul ponte
// Funzioni Thread.
void Pedone
(LPDWORD lpdwParam
);
// Un Pedone.
void Carro
(LPDWORD lpdwParam
);
// Un Carro.
// Handle globali dei semafori e dei mutex: Semafori Corsie, Mutex Var. Glob., Mutex Stream di Output
HANDLE hCorsiaA
[2], hCorsiaR
[2], hPeso, hPersone, hPrint;
// Inizia il programmino...=)
void main
() {
// Conteggio Thread e cicli di wait per il peso.
int c,count =
0;
c= count;
// Var. Flag per la destinazione
int A = ANDATA;
int R = RITORNO;
srand
((unsigned)time
(NULL));
// Generazione del seed per il rand
// Creo i Mutex e i Semafori
hPeso = CreateMutex
(NULL,
false,
NULL);
hPersone = CreateMutex
(NULL,
false,
NULL);
hPrint = CreateMutex
(NULL,
false,
NULL);
for( int i =
0; i<
2; i++
) {
// NB: Ho utilizzato i semafori per essere sicuro di ottenere il numero di corsia giusto all'interno dei thread.
hCorsiaA
[i
] = CreateSemaphore
(NULL,
1,
1,
NULL);
hCorsiaR
[i
] = CreateSemaphore
(NULL,
1,
1,
NULL);
}
HANDLE hNow;
// Handle temporaneo per il resume dei thread.
printf("Pressa un tasto per generare un carro o un pitone. q per uscire.\n");
// Comincia il ciclo di creazione dei Thread :|
do{
if(GetRandom
(0,
1)) { // Creo un Carro se GetRandom ritorna 1
if(GetRandom
(0,
1)){ // La destinazione è ANDATA se il GetRandom ritorna 1
WaitForSingleObject
(hPrint,INFINITE
);
printf("Il Carro vuole andare! Peso attuale: %d\n",PesoAttuale
);
ReleaseMutex
(hPrint
);
hNow = CreateThread
(NULL,
0,
(LPTHREAD_START_ROUTINE
) Carro,
(LPVOID
) &
(A
), CREATE_SUSPENDED,
NULL);
c++;
do{ // Inizia il ciclo per il controllo Peso
if(PesoAttuale+PESOC<MAXPESO
) { // Controllo peso: OK
ResumeThread
(hNow
);
break;
} else { // Controllo Peso: NOK
count++;
WaitForSingleObject
(hPrint,INFINITE
);
printf("Peso Massimo raggiunto, Aspetto! Peso Attuale: %d - Ho aspettato %d volte\n", PesoAttuale,count
);
ReleaseMutex
(hPrint
);
Sleep
(10000);
// Aspetto un pochito! =)
continue;
}
}while(1); count =
0;
// Fine del ciclo di controllo Peso
} else { // La destinazione è RITORNO se il GetRandom ritorna 0
WaitForSingleObject
(hPrint,INFINITE
);
printf("Il Carro vuole tornare! Peso attuale: %d\n",PesoAttuale
);
ReleaseMutex
(hPrint
);
hNow = CreateThread
(NULL,
0,
(LPTHREAD_START_ROUTINE
) Carro,
(LPVOID
) &
(R
), CREATE_SUSPENDED,
NULL);
c++;
do{ // Inizia il ciclo per il controllo Peso
if(PesoAttuale+PESOC<MAXPESO
) { // Controllo peso: OK
ResumeThread
(hNow
);
break;
} else { // Controllo Peso: NOK
count++;
WaitForSingleObject
(hPrint,INFINITE
);
printf("Peso Massimo raggiunto, Aspetto! Peso Attuale: %d - Ho aspettato %d volte\n", PesoAttuale,count
);
ReleaseMutex
(hPrint
);
Sleep
(10000);
// Aspetto un pochito! =)
continue;
}
}while(1); count =
0;
// Fine del ciclo di controllo Peso
}
} else { // Creo un Pedone se GetRandom ritorna 0
if(GetRandom
(0,
1)){ // La destinazione è ANDATA se il GetRandom ritorna 1
WaitForSingleObject
(hPrint,INFINITE
);
printf("Il Pedone vuole andare! Peso attuale: %d\n",PesoAttuale
);
ReleaseMutex
(hPrint
);
hNow = CreateThread
(NULL,
0,
(LPTHREAD_START_ROUTINE
) Pedone,
(LPVOID
) &
(A
), CREATE_SUSPENDED,
NULL);
c++;
do{ // Inizia il ciclo per il controllo Peso
if(PesoAttuale+PESOP<MAXPESO
) { // Controllo peso: OK
ResumeThread
(hNow
);
break;
} else { // Controllo Peso: NOK
count++;
WaitForSingleObject
(hPrint,INFINITE
);
printf("Peso Massimo raggiunto, Aspetto! Peso Attuale: %d - Ho aspettato %d volte\n", PesoAttuale,count
);
ReleaseMutex
(hPrint
);
Sleep
(10000);
// Aspetto un pochito! =)
continue;
}
}while(1); count =
0;
// Fine del ciclo di controllo Peso
} else { // La destinazione è RITORNO se il GetRandom ritorna 1
WaitForSingleObject
(hPrint,INFINITE
);
printf("Il Pedone vuole tornare! Peso attuale: %d\n",PesoAttuale
);
ReleaseMutex
(hPrint
);
hNow = CreateThread
(NULL,
0,
(LPTHREAD_START_ROUTINE
) Pedone,
(LPVOID
) &
(R
), CREATE_SUSPENDED,
NULL);
c++;
do{ // Inizia il ciclo per il controllo Peso
if(PesoAttuale+PESOP<MAXPESO
) { // Controllo peso: OK
ResumeThread
(hNow
);
break;
} else { // Controllo Peso: NOK
count++;
WaitForSingleObject
(hPrint,INFINITE
);
printf("Peso Massimo raggiunto, Aspetto! Peso Attuale: %d - Ho aspettato %d volte\n", PesoAttuale,count
);
ReleaseMutex
(hPrint
);
Sleep
(10000);
// Aspetto un pochito! =)
continue;
}
}while(1); count =
0;
// Fine del ciclo di controllo Peso
}
}
} while(getch
()!=
'q');
// Fine del ciclo di creazione Thread!!! :|
printf("\n*) Numero Persone sulle corsie: %d\n*) Peso Attuale: %d\nHo creato %d thread!\n\n",Persone
[0]+Persone
[1],PesoAttuale,c
);
// Riassuntino finale
}
void Pedone
(LPDWORD lpdparm
){
DWORD result;
// Variabile per il risultato dei Wait.
int nCorsia;
// Numero corsia assegnata
int dst = *
(int *
) lpdparm;
// Destinazione del viaggio
if(dst==
0) { // Caso destinazione ANDATA
// Assegno un numero di corsia.
result = WaitForMultipleObjects
(2,hCorsiaR,
false,INFINITE
);
nCorsia = result - WAIT_OBJECT_
0 +
1;
// Caso in cui non vi siano persone sulla stessa corsia
if(Persone
[nCorsia-
1]==
0) WaitForSingleObject
(hCorsiaA
[nCorsia-
1],INFINITE
);
// Occupo la corsia di andata.
// Rilascio quella di ritorno. Permetto ad altri di procedere nello stesso senso
ReleaseSemaphore
(hCorsiaR
[nCorsia-
1],
1,
NULL);
WaitForSingleObject
(hPeso,INFINITE
);
PesoAttuale+=PESOP;
// Una persona in più --> Aumento Peso
ReleaseMutex
(hPeso
);
WaitForSingleObject
(hPersone,INFINITE
);
Persone
[nCorsia-
1]++;
// Una persona in più --> Aumento Persone sulla corsia.
ReleaseMutex
(hPersone
);
WaitForSingleObject
(hPrint,INFINITE
);
printf("Il Pedone e' partito (ANDATA). Numero Corsia: %d\n",nCorsia
);
ReleaseMutex
(hPrint
);
Sleep
(5000);
// Persona in viaggio di ANDATA
WaitForSingleObject
(hPrint,INFINITE
);
printf("Il Pedone e' arrivato(ANDATA). Numero Corsia: %d\n",nCorsia
);
ReleaseMutex
(hPrint
);
WaitForSingleObject
(hPersone,INFINITE
);
Persone
[nCorsia-
1]--;
// Una persona in meno --> Diminuisco Persone sulla corsia
ReleaseMutex
(hPersone
);
WaitForSingleObject
(hPeso,INFINITE
);
PesoAttuale-=PESOP;
// Una persona in meno --> Diminuisco Peso
ReleaseMutex
(hPeso
);
// Caso in cui non vi siano persone sulla corsia
// Rilascio la corsia di andata. Permetto ad altri di tornare.
if(Persone
[nCorsia-
1]==
0) ReleaseSemaphore
(hCorsiaA
[nCorsia-
1],
1,
NULL);
WaitForSingleObject
(hPrint,INFINITE
);
// Riassuntino... =)
printf("\n*) Numero Persone sulle corsie: %d\n*) Peso Attuale: %d\n\n",Persone
[0]+Persone
[1],PesoAttuale
);
ReleaseMutex
(hPrint
);
}
else { // Caso destinazione RITORNO
// Assegno un numero di corsia.
result = WaitForMultipleObjects
(2,hCorsiaA,
false,INFINITE
);
nCorsia = result - WAIT_OBJECT_
0+
1;
// Caso in cui non vi siano persone sulla stessa corsia
if(Persone
[nCorsia-
1]==
0) WaitForSingleObject
(hCorsiaR
[nCorsia-
1],INFINITE
);
// Occupo la corsia di ritorno
// Rilascio quella di andata. Permetto ad altri di procedere nello stesso senso
ReleaseSemaphore
(hCorsiaA
[nCorsia-
1],
1,
NULL);
WaitForSingleObject
(hPersone,INFINITE
);
Persone
[nCorsia-
1]++;
// Una persona in più --> Aumento Peso
ReleaseMutex
(hPersone
);
WaitForSingleObject
(hPeso,INFINITE
);
PesoAttuale+=PESOP;
// Una persona in più --> Aumento Persone sulla corsia.
ReleaseMutex
(hPeso
);
WaitForSingleObject
(hPrint,INFINITE
);
printf("Il Pedone e' partito (RITORNO). Numero Corsia: %d\n",nCorsia
);
ReleaseMutex
(hPrint
);
Sleep
(5000);
// Persona in viaggio di RITORNO
WaitForSingleObject
(hPrint,INFINITE
);
printf("Il Pedone e' arrivato(RITORNO). Numero Corsia: %d\n",nCorsia
);
ReleaseMutex
(hPrint
);
WaitForSingleObject
(hPersone,INFINITE
);
Persone
[nCorsia-
1]--;
// Una persona in meno --> Diminuisco Persone sulla corsia
ReleaseMutex
(hPersone
);
WaitForSingleObject
(hPeso,INFINITE
);
PesoAttuale-=PESOP;
// Una persona in meno --> Diminuisco Peso
ReleaseMutex
(hPeso
);
// Caso in cui non vi siano persone sulla corsia
// Rilascio la corsia di ritorno. Permetto ad altri di andare.
if(Persone
[nCorsia-
1]==
0) ReleaseSemaphore
(hCorsiaR
[nCorsia-
1],
1,
NULL);
WaitForSingleObject
(hPrint,INFINITE
);
// Riassuntino... =)
printf("\n*) Numero Persone sulle corsie: %d\n*) Peso Attuale: %d\n\n",Persone
[0]+Persone
[1],PesoAttuale
);
ReleaseMutex
(hPrint
);
}
}
void Carro
(LPDWORD lpdparm
){
DWORD result;
// In questo caso è superfluo
int dst = *
(int *
) lpdparm;
// Destinazione del viaggio
if(dst==
0) { // Caso destinazione ANDATA
// Occupo entrambe le corsie.
result = WaitForMultipleObjects
(2,hCorsiaR,
true,INFINITE
);
if(Persone
[0] ==
0) WaitForSingleObject
(hCorsiaA
[0],INFINITE
);
if(Persone
[1] ==
0) WaitForSingleObject
(hCorsiaA
[1],INFINITE
);
// Rilascio entrambe le corsie di ritorno per permettere ad altri di accodarsi.
ReleaseSemaphore
(hCorsiaR
[0],
1,
NULL);
ReleaseSemaphore
(hCorsiaR
[1],
1,
NULL);
WaitForSingleObject
(hPeso,INFINITE
);
PesoAttuale+=PESOC;
// Aggiungo il peso di un Carro
ReleaseMutex
(hPeso
);
WaitForSingleObject
(hPersone,INFINITE
);
// Un carro vale due persone!!! Aggiungo due persone
Persone
[0]++;
Persone
[1]++;
ReleaseMutex
(hPersone
);
WaitForSingleObject
(hPrint,INFINITE
);
printf("Il Carro e' partito (ANDATA).\n");
ReleaseMutex
(hPrint
);
Sleep
(5000);
// Carro in viaggio di ANDATA
WaitForSingleObject
(hPrint,INFINITE
);
printf("Il Carro e' arrivato(ANDATA).\n");
ReleaseMutex
(hPrint
);
WaitForSingleObject
(hPersone,INFINITE
);
// Un carro vale due persone!!! Tolgo due persone
Persone
[0]--;
Persone
[1]--;
ReleaseMutex
(hPersone
);
WaitForSingleObject
(hPeso,INFINITE
);
PesoAttuale-=PESOC;
// Tolgo il Peso di un Carro
ReleaseMutex
(hPeso
);
// Caso in cui non ci son persone in entrambe le corsie
// Rilascio entrambe le corsie di andata, per permettere ad altri di tornare.
if(Persone
[0]==
0) ReleaseSemaphore
(hCorsiaA
[0],
1,
NULL);
if(Persone
[1]==
0) ReleaseSemaphore
(hCorsiaA
[1],
1,
NULL);
WaitForSingleObject
(hPrint,INFINITE
);
// Riassuntino... =)
printf("\n*) Numero Persone sulle corsie: %d\n*) Peso Attuale: %d\n\n",Persone
[0]+Persone
[1],PesoAttuale
);
ReleaseMutex
(hPrint
);
}
else { // Caso destinazione RITORNO
// Occupo entrambe le corsie.
result = WaitForMultipleObjects
(2,hCorsiaA,
true,INFINITE
);
if(Persone
[0] ==
0) WaitForSingleObject
(hCorsiaR
[0],INFINITE
);
if(Persone
[1] ==
0) WaitForSingleObject
(hCorsiaR
[1],INFINITE
);
WaitForSingleObject
(hPeso,INFINITE
);
PesoAttuale+=PESOC;
// Aggiungo il peso di un Carro
ReleaseMutex
(hPeso
);
WaitForSingleObject
(hPersone,INFINITE
);
// Un carro vale due persone!!! Aggiungo due persone
Persone
[0]++;
Persone
[1]++;
ReleaseMutex
(hPersone
);
// Rilascio entramebe le corsie di andata per permettere ad altri di accodarsi.
ReleaseSemaphore
(hCorsiaA
[0],
1,
NULL);
ReleaseSemaphore
(hCorsiaA
[1],
1,
NULL);
WaitForSingleObject
(hPrint,INFINITE
);
printf("Il Carro e' partito (RITORNO).\n");
ReleaseMutex
(hPrint
);
Sleep
(5000);
// Carro in viaggio di RITORNO
WaitForSingleObject
(hPrint,INFINITE
);
printf("Il Carro e' arrivato(RITORNO).\n");
ReleaseMutex
(hPrint
);
WaitForSingleObject
(hPersone,INFINITE
);
// Un carro vale due persone!!! Tolgo due persone
Persone
[0]--;
Persone
[1]--;
ReleaseMutex
(hPersone
);
WaitForSingleObject
(hPeso,INFINITE
);
PesoAttuale-=PESOC;
// Tolgo il Peso di un Carro
ReleaseMutex
(hPeso
);
// Caso in cui non ci son persone in entrambe le corsie
// Caso in cui non ci son persone in entrambe le corsie
// Rilascio entrambe le corsie di andata, per permettere ad altri di tornare.
if(Persone
[0]==
0) ReleaseSemaphore
(hCorsiaR
[0],
1,
NULL);
if(Persone
[1]==
0) ReleaseSemaphore
(hCorsiaR
[1],
1,
NULL);
WaitForSingleObject
(hPrint,INFINITE
);
// Riassuntino... =)
printf("\n*) Numero Persone sulle corsie: %d\n*) Peso Attuale: %d\n\n",Persone
[0]+Persone
[1],PesoAttuale
);
ReleaseMutex
(hPrint
);
}
}
Torna a Lab Sistemi Operativi
Non ci sono commenti in questa pagina. [Scrivi commento]