//operating systems
//assignment #1
//this is busy.cpp
//compile : g++ busy.cpp

#include < iostream.h >
#include < sys/types.h >
#include < sys/ipc.h >
#include < sys/shm.h >
#include < fcntl.h >



//variables to denote turn
const short i = 0 ;
const short j = 1 ;


//structure to hold shared memory
typedef struct
{
	bool flag[ 2 ] ;
	int  value ;
	unsigned short turn ;
} SharedMemory ;


//using peterson's algorithm
class PetersonsAlgorithm
{
	public :
		//init class
		PetersonsAlgorithm( SharedMemory * sharedMemory )
		{
			this->sharedMemory = sharedMemory ;
			this->sharedMemory->flag[ 0 ] = 0 ;
			this->sharedMemory->flag[ 1 ] = 0 ;
			this->sharedMemory->value		= 0 ;
			this->sharedMemory->turn		= 0 ;
		}
		~PetersonsAlgorithm()
		{
			sharedMemory = 0 ;
		}

		void processI( void )
		{
			unsigned int line = 0 ;

			while( line < 50000 )
			{
				line++ ;
				sharedMemory->flag[ i ] = true ;
				sharedMemory->turn = j ;

				//busy wait here
				while( sharedMemory->flag[ j ] &&
						 sharedMemory->turn == j )
						 ;

				//critical section
				sharedMemory->value++ ;

				//ready for processJ ;
				sharedMemory->flag[ i ] = false ;
			}
		}

		
		void processJ( void )
		{
			unsigned int line = 0 ;

			while( line < 50000 )
			{
				line++ ;
				sharedMemory->flag[ j ] = true ;
				sharedMemory->turn = i ;

				//busy wait here
				while( sharedMemory->flag[ i ] &&
						 sharedMemory->turn == i )
						 ;

				//critical region
				sharedMemory->value++ ;

				//ready for processI
				sharedMemory->flag[ j ] = false ;
			}
		}


		//return value of the shared memory
		int getValue()
		{
			return sharedMemory->value ;
		}


	private :
		//the shared memory
		SharedMemory *sharedMemory ;
} ;


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


	//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
	PetersonsAlgorithm pA( sMemory ) ;
	
	//zero it, finished with pointer
	sMemory = 0 ;
	
	

	//create first process, processI
   if( ( pid1 = fork() ) == 0 )
 		pA.processI() ;
	
	//create second process, processJ
   if( ( pid1 != 0 )&&( pid2 = fork() ) == 0 )
		pA.processJ() ;




	//only need one output to screen
   if( ( pid1 != 0 )&&( pid2 != 0 ) )
	{
		//block the parent for 2 seconds
		sleep( 2 );  
	   cout << "the value is..... " << pA.getValue() << endl ;
		cout << "\t\t fin" << endl ;
	

		//remove shared memory
		if( shmctl( shmid, IPC_RMID, 0 ) == -1 )
		{
			cerr << "shmctl" ;
			exit( -1 ) ;
		}
    }

	return 0 ;
}