1
0
This repository has been archived on 2025-11-01. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
ss-monorepo/P5/smt4497-P5/smt4497-P5.cpp
2025-10-10 02:17:07 +02:00

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;
}