Sunday 5 October 2014

C Program To Implement Bank Token Generation Machine(Using threads and Semaphores)

/*
Problem Description
A bank has three entrances and eight counters. Each entrance has a token issuing machine next to it. A customer enters or exits the bank through any of the entrances. He/she then collects a token and waits for the token number to be 'called' by any counter. The calling of a token is taken to mean that the customer finishes his/her job and exits from the bank.
It must be ensured that:
  • Tokens must be issued in strict sequence.
  • No token number must be skipped or issued twice.
  • Counters should call the tokens in a strict ascending order.
  • No token should be skipped or called twice.
  • No counter can call a token number that has not been issued at that time.
Write a program that uses multiple threads for the token issuing machines and counters with appropriate synchronisation primitives*/

//Solution

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <semaphore.h>

#define MAXCUSTOMERS        2000000
#define TOKEN_MACHINES      3
#define SEVICE_COUNTERS     8

int nitems;
int buff[MAXCUSTOMERS];
struct {
  sem_t mutexpro, mutexcon , nstored;  
  int nput;
  int nval;
  int nvalcon;
} shared;

void *prod(void *), *cons(void *);

int main (int argc, char *argv[])
{
     int i, nthreads, countpro[3],countcon[8], totalsum = 0;
     pthread_t tid_prod[TOKEN_MACHINES], tid_cons[SEVICE_COUNTERS];

     if (argc != 2) {
 fprintf(stderr, "Usage: mutexes #maxnumberOfCUSTOMER\n");
 exit(1);
     }

     if ((nitems = atoi (argv[1])) > MAXCUSTOMERS)
 nitems = MAXCUSTOMERS;

     sem_init (&shared.mutexpro, 0, 1);
     sem_init (&shared.mutexcon, 0, 1);
     sem_init (&shared.nstored, 0, 0);

     for (i=0; i<3; i++) {
 countpro[i] = 0;
 pthread_create(&tid_prod[i], NULL, prod, &countpro[i]);
     }
     
     for (i=0; i<8; i++) {      
 countcon[i]=0;
 pthread_create(&tid_cons[i], NULL, cons, &countcon[i]);
     }

     for (i=0; i<3; i++) {
 pthread_join(tid_prod[i], NULL);
  totalsum += countpro[i];
     }
     
     for (i=0; i<8; i++) {
pthread_join(tid_cons[i], NULL);
      printf("\nCustomers served by %d counter are %d\n", i, countcon[i]);
     }

     sem_destroy (&shared.mutexpro);
     sem_destroy (&shared.mutexcon);
     sem_destroy (&shared.nstored);
     exit(0);
}

void *prod(void *arg)
{
     for ( ; ; ) {
 sem_wait (&shared.mutexpro);
 if (shared.nput >= nitems) {
      sem_post (&shared.mutexpro);
      return (NULL);
 }

 buff[shared.nput] = shared.nval;
 printf("The token issued at entrance %d \n",buff[shared.nput]);
 shared.nput++;
 shared.nval++;
 sem_post (&shared.mutexpro); 
 sem_post (&shared.nstored);
 *((int *) arg) += 1;
     }
}

void *cons(void *arg)
{
     int i;
     
     for ( ; ;) {
 sem_wait (&shared.mutexcon);
 if (shared.nvalcon >= nitems) {
      sem_post (&shared.mutexcon);
      return (NULL);
 }
          sem_wait (&shared.nstored);    
          printf("The customer served is %d \n",buff[shared.nvalcon]);
 shared.nvalcon = shared.nvalcon + 1;
 sem_post (&shared.mutexcon);
       *((int *) arg) += 1;
     }     
     return(NULL);

}