\Nessuna differenza.
// 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.
#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
}
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! Ho aspettato %d volte\n", 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);
// Se non ci sono persone su entrambe le corsie, occupo entrambe di andata.
if(Persone[0]==0 && Persone[1]==0) WaitForMultipleObjects(2,hCorsiaA,true,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
if(Persone[0]==0 && Persone[1]==0) {
// Rilascio entrambe le corsie di andata, per permettere ad altri di tornare.
ReleaseSemaphore(hCorsiaA[0],1,NULL);
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);
// Se non ci sono persone su entrambe le corsie, occupo entrambe di ritorno.
if(Persone[0]==0 && Persone[1]==0) WaitForMultipleObjects(2,hCorsiaR,true,INFINITE);
// Rilascio entramebe le corsie di andata per permettere ad altri di accodarsi.
ReleaseSemaphore(hCorsiaA[0],1,NULL);
ReleaseSemaphore(hCorsiaA[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 (RITORNO).\n");
ReleaseMutex(hPrint);
Sleep(5000); // Carro in viaggio di RITORNO
WaitForSingleObject(hPrint,INFINITE);
printf("Il Carro e' arrivato(RITORNO).\n");
ReleaseMutex(hPrint);