Universidad de Costa Rica

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

CI-0122 Sistemas operativos

Ejemplos

CI0122 / Ejemplos


// Compile with g++ h20.cc -lpthread
//
#include <cstdlib>
#include <iostream>
#include <pthread.h>
#include <semaphore.h>

using namespace std;

#define NUMTHRDS 100
int status;
int n = 256;
pthread_t thds[NUMTHRDS];
pthread_mutex_t mutex;

sem_t sH, sO;

int cH = 0, cO = 0;

int main ( int argc, char *argv[] );
void *H ( void *arg );
void *O ( void *arg );


int main ( int argc, char *argv[] ) {

  int i;

  sem_init( &sH, 0, 0 );
  sem_init( &sO, 0, 0 );

  pthread_attr_t attr;
  pthread_mutex_init ( &mutex, NULL );
  pthread_attr_init ( &attr );
  pthread_attr_setdetachstate ( &attr, PTHREAD_CREATE_JOINABLE );

  for ( i = 0; i < NUMTHRDS; i++ ) {
    if ( 0 == ( rand() % 2 ) )
       pthread_create ( &thds[i], &attr, H, ( void * ) i );
    else
       pthread_create ( &thds[i], &attr, O, ( void * ) i );
  }

  pthread_attr_destroy ( &attr );

  for ( i = 0; i < NUMTHRDS; i++ ) {
    pthread_join ( thds[i], ( void ** ) &status );
  }

  pthread_mutex_destroy ( &mutex );
//  pthread_exit ( NULL );

  cout << "\n";
  cout << "  Normal end of execution.\n";

  return 0;
}


void *H ( void *arg ) {

   int i;

   i = (long) arg;

   pthread_mutex_lock ( &mutex );	// Lock access to cH and cO variables

   if ( (cH > 0)  && (cO > 0) ) {	// I'm an H, have we the others?
      cH--;	// Using an H
      cO--;	// Using an O
      cout << "Soy un H, hice agua: " << i << endl;
      pthread_mutex_unlock ( &mutex );	//Free the mutex
      sem_post( &sH );		// Free the waiting thread
      sem_post( &sO );		// Free the waiting thread
   } else {
      cH++;			// Increment the H count
      cout << "Soy un H, estoy esperando: " << i << endl;
      pthread_mutex_unlock ( &mutex );	// Free the mutex
      sem_wait( &sH );		// Wait for the others
   }

   pthread_exit ( ( void * ) 0 );
}


void *O ( void *arg ) {

   int i;

   i = (long) arg;

   pthread_mutex_lock ( &mutex );  // Lock access to cH and cO variables

   if ( cH > 1 ) {	// I'm an O, have we at least two H's?
      cH-=2;		// We use two H's
      cout << "Soy un O, hice agua: " << i << endl;
      pthread_mutex_unlock ( &mutex );	//Free mutex
      sem_post( &sH );	// Free the waiting threads
      sem_post( &sH );
   } else {
      cO++;		// Increment O count, then wait
      cout << "Soy un O, estoy esperando: " << i << endl;
      pthread_mutex_unlock ( &mutex );	// Free mutex
      sem_wait( &sH );	// Wait for other threads
   }

   pthread_exit ( ( void * ) 0 );	// Finish this thread
}