130 lines
3.6 KiB
C++
130 lines
3.6 KiB
C++
#include "smt4497-p5.h"
|
|
#define INCREMENTS (100*1000)
|
|
#define THREADS 20
|
|
#define ITERATIONS 100
|
|
|
|
using namespace ss;
|
|
|
|
static HANDLE mutex;
|
|
static HANDLE* turn_events;
|
|
static Dbg _dbg(true);
|
|
|
|
int main(int argc, char* argv[], char* envp[])
|
|
{
|
|
setlocale(LC_ALL, "Spanish");
|
|
|
|
/*printf("\nEmpezando sin mutex...\n");
|
|
for (int i = 1; i <= ITERATIONS; i++)
|
|
{
|
|
test_simple_non_reentrant_thread(INCREMENTS, THREADS);
|
|
}
|
|
printf("\nEmpezando con mutex...\n");
|
|
for (int i = 1; i <= ITERATIONS; i++)
|
|
{
|
|
test_simple_non_reentrant_thread_mutex(INCREMENTS, THREADS);
|
|
}*/
|
|
|
|
test_thread_turns(THREADS);
|
|
|
|
printf("\nPor favor pulse ENTER para terminar...");
|
|
(void)getchar();
|
|
return 0;
|
|
}
|
|
|
|
VOID simple_non_reentrant_thread(int times, int* pCounter)
|
|
{
|
|
for (int i = 0; i < times; i++)
|
|
{
|
|
*pCounter += times + 1;
|
|
*pCounter -= times + 1;
|
|
}
|
|
}
|
|
|
|
static BOOL test_simple_non_reentrant_thread(int increments, int threads_number)
|
|
{
|
|
int counter = 0;
|
|
_dbg.CronoInicio();
|
|
thread* threads = new thread[threads_number];
|
|
for (int i = 0; i < threads_number; i++)
|
|
{
|
|
threads[i] = thread(simple_non_reentrant_thread, increments, &counter);
|
|
_dbg.CheckError(threads[i].native_handle() == NULL, "No se pudo crear el hilo");
|
|
}
|
|
for (int i = 0; i < threads_number; i++)
|
|
threads[i].join();
|
|
double secs = _dbg.CronoLee();
|
|
printf("[SIN MUTEX] Contador vale: %d (calculado con %d hilos, en %f segundos)\n", counter, threads_number, secs);
|
|
return counter == 0;
|
|
}
|
|
|
|
VOID simple_non_reentrant_thread_mutex(int times, int* pCounter)
|
|
{
|
|
DWORD res = WaitForSingleObject(mutex, INFINITE); // critical section begins
|
|
_dbg.CheckError(res != 0, 2, "Error en el bloqueo\n");
|
|
for (int i = 0; i < times; i++)
|
|
{
|
|
*pCounter += times + 1;
|
|
*pCounter -= times + 1;
|
|
}
|
|
_dbg.CheckError(ReleaseMutex(mutex) == FALSE, 1, "Error liberando mutex\n"); // critical section ends
|
|
|
|
}
|
|
static BOOL test_simple_non_reentrant_thread_mutex(int increments, int threads_number)
|
|
{
|
|
int counter = 0;
|
|
_dbg.CronoInicio();
|
|
mutex = CreateMutexA(NULL, FALSE, NULL);
|
|
_dbg.CheckError(mutex == NULL, 1, "Error creando el mutex\n");
|
|
thread* threads = new thread[threads_number];
|
|
for (int i = 0; i < threads_number; i++)
|
|
{
|
|
threads[i] = thread(simple_non_reentrant_thread_mutex, increments, &counter);
|
|
_dbg.CheckError(threads[i].native_handle() == NULL, "No se pudo crear el hilo");
|
|
}
|
|
for (int i = 0; i < threads_number; i++)
|
|
threads[i].join();
|
|
double secs = _dbg.CronoLee();
|
|
printf("[CON MUTEX] Contador vale: %d (calculado con %d hilos, en %f segundos)\n", counter, threads_number, secs);
|
|
return counter == 0;
|
|
}
|
|
|
|
static VOID thread_turns(int thread_number)
|
|
{
|
|
WaitForSingleObject(turn_events[thread_number], INFINITE);
|
|
for (int i = 0; i < thread_number; i++)
|
|
printf(" ");
|
|
printf("hilo %i iniciado >>", thread_number);
|
|
for (int i = 0; i < thread_number; i++)
|
|
printf(" ");
|
|
printf("<< hilo %i finalizado\n", thread_number);
|
|
SetEvent(turn_events[thread_number + 1]);
|
|
}
|
|
|
|
static VOID test_thread_turns(int thread_numbers)
|
|
{
|
|
turn_events = new HANDLE[thread_numbers + 1];
|
|
for (int i = 0; i <= thread_numbers; i++)
|
|
{
|
|
turn_events[i] = CreateEventA(NULL, FALSE, FALSE, NULL);
|
|
_dbg.CheckError(turn_events[i] == NULL, 1, "Error creando el evento\n");
|
|
}
|
|
|
|
thread* threads = new thread[thread_numbers];
|
|
for (int i = 0; i < thread_numbers; i++)
|
|
{
|
|
threads[i] = thread(thread_turns, i);
|
|
_dbg.CheckError(threads[i].native_handle() == NULL, "No se pudo crear el hilo");
|
|
}
|
|
|
|
SetEvent(turn_events[0]);
|
|
|
|
for (int i = 0; i < thread_numbers; i++)
|
|
threads[i].join();
|
|
|
|
for (int i = 0; i <= thread_numbers; i++)
|
|
CloseHandle(turn_events[i]);
|
|
|
|
delete[] turn_events;
|
|
delete[] threads;
|
|
}
|