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