#include <stdio.h>
#include <process.h>
#include <windows.h>
#include <conio.h>
/*
Creiamo 2 thread somma e sottrai, che condividono la risorsa numero e che corrispettivamente aggiungono e
sottraggono 1 al valore corrente di numero.
*/
DWORD somma(LPDWORD b); //Thread per sommare 1 al valore di numero
DWORD sottrai(LPDWORD b); //Thread per sottrarre 1 al valore di numero
DWORD finito(LPDWORD b); //Thread per gestire la fine del processo
//Funzione principale
void main()
{int numero=0,fine=0;
HANDLE hmutexNUM; //Handle per gestire il mutex per l'unica risorsa condivisa
HANDLE hThreadSomma,hThreadFine,hThreadSottrai; //Handles per gestire i 3 thread
DWORD dwThreadIdFinito,dwThreadIdSomma,dwThreadIdSottrai; //Per gestire l'id dei Threads
/*
HANDLE CreateMutex(
LPSECURITY_ATTRIBUTES lpMutexAttributes,
// Puntatore alle impostazioni di sicurezza (solitamente posto a NULL)
BOOL bInitialOwner, // Specifica il proprietario del Mutex, se TRUE il processo chiamante è il proprietario
LPCTSTR lpName // Nome del mutex (tra virgolette)
);
*/
hmutexNUM=CreateMutex(NULL,TRUE,"mutexNUM"); //crea il mutex
if (hmutexNUM==NULL) //controlla se la creazione è avvenuta con successo
printf("errore creazione mutex");
/*
HANDLE CreateThread(
LPSECURITY_ATTRIBUTES lpThreadAttributes, // Puntatore alle impostazioni di sicurezza (solitamente posto a NULL)
DWORD dwStackSize, // Grandezza iniziale dello stack (solitamente posto a 0)
LPTHREAD_START_ROUTINE lpStartAddress, // Richiama la funzione con il tipo LPTHREAD_START_ROUTINE
LPVOID lpParameter, // Parametri della funzione
DWORD dwCreationFlags, // Flag di creazione.
Se 0 il thread viene creato immediatamente
Se CREATE_SUSPENDED viene creato in modalità sospesa
(da riattivare con ResumeThread)
LPDWORD lpThreadId // Puntatore che riceverà l'id del Thread
);
*/
//CREAZIONE THREAD
hThreadFine=CreateThread(NULL,0,(LPTHREAD_START_ROUTINE) finito,(LPVOID) &fine,0,&dwThreadIdFinito);
hThreadSomma=CreateThread(NULL,0,(LPTHREAD_START_ROUTINE) somma,(LPVOID) &numero,CREATE_SUSPENDED,&dwThreadIdSomma);
hThreadSottrai=CreateThread(NULL,0,(LPTHREAD_START_ROUTINE) sottrai,(LPVOID) &numero,CREATE_SUSPENDED,&dwThreadIdSottrai);
//Settiamo priorità diverse ai Thread
SetThreadPriority(hThreadSomma,THREAD_PRIORITY_HIGHEST);
SetThreadPriority(hThreadSottrai,THREAD_PRIORITY_LOWEST);
//Controlla se la creazione è avvenuta con successo
if (hThreadFine==NULL || hThreadSomma==NULL || hThreadSottrai==NULL)
printf("Creazione Thread fallita");
else
{
//Attiva i Thread precedentemente creati in modalità sospesa
ResumeThread(hThreadSomma);
ResumeThread(hThreadSottrai);
while (fine==0); //Attesa attiva (aspetta che fine viene posto ad 1 (tramite input tastiera)
//Termina i Thread con valore di uscita 0.
TerminateThread(hThreadSottrai,0);
TerminateThread(hThreadSomma,0);
TerminateThread(hThreadFine,0);
}
}
DWORD somma(LPDWORD b)
{int *num,fine=0;
num=(int *) b;
HANDLE hmutex; //Creazione variabile di tipo Handle per la gestione del Mutex
/*
HANDLE OpenMutex(
DWORD dwDesiredAccess, // Flag di accesso
Se MUTEX_ALL_ACCESS Permette tutti i tipi di accesso
Se SYNCHRONIZE Permette al mutex di usare funzioni di Wait e Release
BOOL bInheritHandle, // Indica se il Mutex è ereditabile (TRUE/FALSE)
LPCTSTR lpName // Nome del Mutex da aprire
);
*/
hmutex=OpenMutex(EVENT_MODIFY_STATE|SYNCHRONIZE,FALSE,"mutexNUM");
while (fine==0);
{
/*
WaitForSingleObject con ReleaseMutex permettono l'accesso esclusivo ad una risorsa condivisa tra Threads
DWORD WaitForSingleObject(
HANDLE hHandle, // Indica l'oggetto di cui si attende il rilascio
DWORD dwMilliseconds // Indica il tempo in millisecondi da attendere, (oppure INFINITE)
)
*/
WaitForSingleObject(hmutex,INFINITE);
(*num)++;
printf("Somma: %d\n",*num);
ReleaseMutex(hmutex);//rilascia il mutex
Sleep(50);
}
return 0;
}
DWORD sottrai(LPDWORD b)
{
int *num,fine=0;
num=(int *) b;
HANDLE hmutex;
hmutex=OpenMutex(EVENT_MODIFY_STATE|SYNCHRONIZE,FALSE,"mutexNUM");
while (fine==0)
{
WaitForSingleObject(hmutex,INFINITE);
(*num)--;
printf("Sottrai: %d\n",*num);
ReleaseMutex(hmutex);
Sleep(50);
}
return 0;
}
DWORD finito(LPDWORD b)
/*
Quando l'utente digita un qualunque carattere da tastiera, pone fine = 1
Implicando l'interruzione del processo (in particolare dei Threads)
*/
{int *fine;
fine=(int *) b;
_getch();
*fine=1;
return 0;
}