Universidad de Costa Rica

Escuela de Ciencias de la Computación e Informática

CI-0122 Sistemas Operativos

Temas

CI0122 / Temas revisados / Semana-06 / PThreads / H2O


/**
 *   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 "Semaphore.h"


// Shared variables
   std::atomic<int> nO( 0 );
   std::atomic<int> nH( 0 );
   std::atomic<int> H2OTotal( 0 );

   Semaphore H( 0 );
   Semaphore O( 0 );
   
/**
 *  Código para el oxígeno
**/
int Oxigeno( int cual ) {

   printf( "Se produjo un atomo de O [H(%d), O(%d)]\t\t[Hilo: %d]\n", (int) nH, (int) nO+1, gettid() );
   if ( nH > 1 ) {		// Check for two hydrogen atoms
      H.Signal();
      H.Signal();
      nH -= 2;
      printf( "\tUn O hizo agua [H(%d), O(%d)]\t\t[Hilo: %d]\n", (int) nH, (int) nO, getpid() );
      H2OTotal++;
   } else {
      nO++;
      O.Wait();
   }

   pthread_exit( 0 );

}


/**
 *  Código para el hidrógeno
**/
int Hidrogeno( int cual ) {

   printf( "Se produjo un atomo de H [H(%d), O(%d)]\t\t[Hilo: %d]\n", (int) nH, (int) nO, gettid() );
   if ( (nH > 0) && (nO > 0) ) {			// Check for another hydrogen atom and one oxygen atom
      H.Signal();
      O.Signal();
      nH--;
      nO--;
      printf( "\tUn H hizo agua [H(%d), O(%d)]\t\t[Hilo: %d]\n", (int) nH, (int) nO, gettid() );
      H2OTotal++;
   } else {
      nH++;   
      H.Wait();
   }

   pthread_exit( 0 );

}


/*
 *
 */
int main( int count, char ** values ) {
   long workers;
   int worker, totalO, totalH;
   std::thread * hilos;

   workers = 100;
   if ( count > 1 ) {
      workers = atol( values[ 1 ] );
   }

   hilos = (std::thread *) calloc( workers, sizeof( std::thread ) );
   srand( gettid() );
   totalH = 0;
   totalO = 0;

// Create atoms
   for ( worker = 0; worker < workers; worker++ ) {
      if ( 0 == (random() & 3) ) {
         hilos[ worker ] = std::thread ( Oxigeno, worker );
         totalO++;
      } else {
         hilos[ worker ] = std::thread ( Hidrogeno, worker );
         totalH++;
      }
   }


   for ( worker = 0; worker < workers; worker++ ) {
      hilos[ worker ].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 );

}