/**
* Resuelve el problema del agua utilizando PThreads
*
* Author: Sistemas Operativos (Francisco Arroyo)
*
* Version: 2023/Abr/23
*
**/
#include <sys/types.h>
#include <unistd.h>
#include <thread>
#include <cstdio>
#include <cstdlib>
#include <atomic>
#include "Sem.h"
// Shared variables
std::atomic<int> nO( 0 );
std::atomic<int> nH( 0 );
std::atomic<int> H2OTotal( 0 );
Sem H( 0 );
Sem O( 0 );
// Sem * mutex = new Sem( 1 );
/**
* Código para el oxígeno
**/
int Oxigeno( int cual, Sem * mutex ) {
int time;
printf( "Se produjo un atomo de O [H(%d), O(%d)]\t\t[Hilo: %d]\n", (int) nH, (int) nO+1, gettid() );
time = random() & 0x1F;
std::this_thread::sleep_for( std::chrono::milliseconds( time ) );
mutex->Wait();
if ( nH > 1 ) { // Check for two hydrogen atoms
nH -= 2;
printf( "\tUn O hizo agua [H(%d), O(%d)]\t\t[Hilo: %d]\n", (int) nH, (int) nO, getpid() );
mutex->Signal();
H.Signal();
H.Signal();
H2OTotal++;
} else {
nO++;
mutex->Signal();
O.Wait();
}
pthread_exit( 0 );
}
/**
* Código para el hidrógeno
**/
int Hidrogeno( int cual, Sem * mutex ) {
int time;
printf( "Se produjo un atomo de H [H(%d), O(%d)]\t\t[Hilo: %d]\n", (int) nH, (int) nO, gettid() );
time = random() & 0x1F;
std::this_thread::sleep_for( std::chrono::milliseconds( time ) );
mutex->Wait();
if ( (nH > 0) && (nO > 0) ) { // Check for another hydrogen atom and one oxygen atom
nH--;
nO--;
printf( "\tUn H hizo agua [H(%d), O(%d)]\t\t[Hilo: %d]\n", (int) nH, (int) nO, gettid() );
mutex->Signal();
H.Signal();
O.Signal();
H2OTotal++;
} else {
nH++;
mutex->Signal();
H.Wait(); // This thread waits until another makes water with it
}
pthread_exit( 0 );
}
/*
*
*/
int main( int count, char ** values ) {
long workers;
int worker, totalO, totalH;
std::thread * hilos;
Sem * mutex = new Sem( 1 );
workers = 100;
if ( count > 1 ) {
workers = atol( values[ 1 ] );
}
hilos = (std::thread *) calloc( workers * 3, sizeof( std::thread ) );
srand( gettid() );
totalH = 0;
totalO = 0;
// Create atoms
for ( worker = 0; worker < workers * 3; worker += 3 ) {
hilos[ worker ] = std::thread ( Hidrogeno, worker, mutex );
hilos[ worker + 1 ] = std::thread ( Oxigeno, worker, mutex );
hilos[ worker + 2 ] = std::thread ( Hidrogeno, worker, mutex );
totalO++;
totalH++;
totalH++;
/**
if ( 0 == (random() & 3) ) {
hilos[ worker ] = std::thread ( Oxigeno, worker, mutex );
totalO++;
} else {
hilos[ worker ] = std::thread ( Hidrogeno, worker, mutex );
totalH++;
}
**/
}
for ( worker = 0; worker < workers * 3; worker += 3 ) {
hilos[ worker ].join();
hilos[ worker + 1 ].join();
hilos[ worker + 2 ].join();
}
printf( "Total hydrogen molecules created: %d\n", totalH );
printf( "Total oxygen molecules created: %d\n", totalO );
if ( (totalH >> 1) > totalO ) {
printf( "Teorethical molecules to produce: %d\n", totalO );
} else {
printf( "Teorethical molecules to produce: %d\n", totalH >> 1 );
}
printf( "Total molecules constructed: %d\n", (int) H2OTotal );
delete mutex;
}