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>

#include "Semaphore.h"


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

   Semaphore H( 1 );
   Semaphore O( 1 );
   Semaphore * mutex = new Semaphore( 1, 1 );
/**
 *  Código para el oxígeno
 **/
int Oxigeno( int cual, Semaphore * 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, Semaphore * 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;
//   Semaphore * mutex = new Semaphore( 1, 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;

}