//assignment# 3
//cop6611
//compile: g++ mutex.cpp
#include < iostream.h >
#include < sys/types.h >
#include < sys/ipc.h >
#include < sys/shm.h >
#include < fcntl.h >
#include < sys/sem.h >
#define SEM_MODE ( 0200 | 0400 | IPC_CREAT)
#define NUM_OF_SEM 3
#define SIZE 10
const int mutex = 0 ;
const int empty = 1 ;
const int full = 2 ;
//printout of out buffer
char textOut[ 37 ] ;
union semun
{
int val ;
struct semid_ds *buf ;
ushort *array ;
};
typedef struct
{
char boundedBuffer[ SIZE ] ;
} SharedMemory ;
int semid ;
//using semaphores now
class BoundedBuffer
{
public :
//init class
BoundedBuffer( SharedMemory * sharedMemory )
{
this->sharedMemory = sharedMemory ;
ptrsembuf = (struct sembuf*)new( struct sembuf ) ;
ptrsembuf->sem_flg = 0 ;
}
//destructor
~BoundedBuffer()
{
sharedMemory = 0 ;
//free up some memory
delete ptrsembuf ;
}
void producer( void )
{
int count = 0 ;
//array of 40 characters
char textIn[ 40 ] = "abcdefghijklmnopqrstuvwxyz0123456789abcd" ;
cout << "\n producer contains\n" << endl ;
for( int i=0; i<40; i++ )
cout << textIn[ i ] ;
cout << "\n\n finished with initial input to producer. wait ~40secs...\n\n" ;
do
{
//p sem
pOperation( empty ) ;
pOperation( mutex ) ;
//critical section
sharedMemory->boundedBuffer[ count % SIZE ] = textIn[ count ] ;
//v sem
vOperation( mutex ) ;
vOperation( full ) ;
}while( ++count < 40 ) ;
}
void consumer( void )
{
int count = 0 ;
do
{
//p sem
pOperation( full ) ;
pOperation( mutex ) ;
//critical section
textOut[ count ] = sharedMemory->boundedBuffer[ count % SIZE ] ;
sleep( 1 ) ;//sleep for one second
//v sem
vOperation( mutex ) ;
vOperation( empty ) ;
}while( ++count < 40 ) ;
cout << "\n\n consumer now contains\n" << endl ;
for( int i=0; i<40; i++ )
cout << textOut[ i ] ;
cout << "\n\n end consumer" << endl ;
}//end consumer
private :
//the shared memory
SharedMemory *sharedMemory ;
//structure for semaphore operations
struct sembuf *ptrsembuf ;
//P operation
void pOperation( int semaphoreID )
{
ptrsembuf->sem_num = semaphoreID ;
ptrsembuf->sem_op = -1 ;
if( semop( semid, ptrsembuf, 1 ) == -1 )
{
cerr << "semop" ;
exit( -1 ) ;
}
}
//V operation
void vOperation( int semaphoreID )
{
ptrsembuf->sem_num = semaphoreID ;
ptrsembuf->sem_op = 1 ;
if( semop( semid, ptrsembuf, 1 ) == -1 )
{
cerr << "semop" ;
exit( -1 ) ;
}
}
} ;
int main( void )
{
//structure which will hold shared memory variables
SharedMemory *sMemory ;
int shmid ; //shared memory ID
int pid1 ; //process id for child 1
int pid2 ; //process id for child 2
union semun initvar ;
int semval ;
//get three semaphores
if( ( semid = semget( IPC_PRIVATE, NUM_OF_SEM, SEM_MODE ) ) == -1 )
{
cerr << "semget" ;
exit( -1 ) ;
}
//start with mutex semaphore
//init var to 1
initvar.val = 1 ;
if( semctl( semid, mutex, SETVAL, initvar ) == -1 )
{
cerr << "semctl" ;
exit( -1 ) ;
}
//check var is = to 1
if( ( semval = semctl( semid, mutex, GETVAL, initvar ) ) == -1 )
{
cerr << "semctl" ;
exit( -1 ) ;
}
cout << "mutex semaphore value is = " << semval << endl ;
//do the same for empty semaphore
//init var to 10
initvar.val = 10 ;
if( semctl( semid, empty, SETVAL, initvar ) == -1 )
{
cerr << "semctl" ;
exit( -1 ) ;
}
//check var is = to 1
if( ( semval = semctl( semid, empty, GETVAL, initvar ) ) == -1 )
{
cerr << "semctl" ;
exit( -1 ) ;
}
cout << "empty semaphore value is = " << semval << endl ;
//now the same for full semaphore
//init var to 0
initvar.val = 0 ;
if( semctl( semid, full, SETVAL, initvar ) == -1 )
{
cerr << "semctl" ;
exit( -1 ) ;
}
//check var is = to 1
if( ( semval = semctl( semid, full, GETVAL, initvar ) ) == -1 )
{
cerr << "semctl" ;
exit( -1 ) ;
}
cout << "the full semaphore value is = " << semval << endl ;
//attempt to attach to an existing memory segment
// the size of SharedMemory structure
if( ( shmid = shmget( IPC_PRIVATE, sizeof( SharedMemory ), IPC_CREAT | 0666 ) ) < 0 )
{
cerr << "shmget" ;
exit( 1 ) ;
}
//attach the shared memory segment
//get address of sMemory
sMemory =(SharedMemory*)shmat( shmid,NULL,0 ) ;
if( sMemory ==(SharedMemory *) -1 )
{
cerr << "shmat" ;
exit( 1 );
}
//send sMemory address to pA's sharedMemory
//create object of petersonsAlgorithm class
BoundedBuffer bb( sMemory ) ;
//zero it, finished with pointer
sMemory = 0 ;
//create the producer
if( ( pid1 = fork() ) == 0 )
bb.producer() ;
//create the consumer
if( ( pid1 != 0 )&&( pid2 = fork() ) == 0 )
bb.consumer() ;
//only need one output to screen
if( ( pid1 != 0 )&&( pid2 != 0 ) )
{
//block the parent for 2 seconds
wait(NULL);
wait(NULL);
//remove shared memory
if( shmctl( shmid, IPC_RMID, 0 ) == -1 )
{
cerr << "shmctl" ;
exit( -1 ) ;
}
//remove semaphore
if( semctl( semid, NUM_OF_SEM, IPC_RMID ) == -1 )
{
cerr << "semctl" ;
exit( -1 ) ;
}
//print textOut
cout << endl ;
for( int i=0; i<37; i++ )
cout << textOut[ i ] ;
cout << "\nend parent\n" ;
}
//all done
return 0 ;
}