# include <iostream.h>
# include <sys/types.h>
# include <sys/ipc.h>
# include <sys/shm.h>
# include <unistd.h>
# include <sys/wait.h>
# define SHM_SIZE 100
# define SHM_MODE  SHM_R/SHM_W

struct criticalSection
{
    int flag[2];     // flag[1] for parent, and flag[2] for child
    int turn;     // turn==1 for parent, and turn==2 for child
    int countA;     // count for after shared memory operation
};

int main ()
{
    int pid, status;     //process id
    int shmid;     //share memory id
    int countB;
    struct criticalSection*  memoryptr;     // pointer point to shared
//memory segment

    //initialize shared memory segment variables
    memoryptr->flag[0] = 0;
    memoryptr->flag[1] = 0;
    memoryptr->turn = 0;

    cout << "process" << '\t'
            << "count (before)" << '\t'
            << "count (after)"<<endl;

    // create shared memory segment, and check if it is successful
    if ((shmid = shmget (IPC_PRIVATE, SHM_SIZE, SHM_MODE)) < 0)
{
cout << "shared memory could not be created." << endl;
return 1;     // terminate with error
}

// get a pointer to the shared memory segment, and check if it is
//successful
/*
else if ((memoryptr = shmat (shmid, 0, 0)) ==  (struct criticalSection*)
- 1 )

{
    cout << " The pointer could not point to the shared memory
segment."
            << endl;
     return 1;
}
*/
// create a child process by fork, and check if it is successful
else if ((pid = fork ()) < 0)
{
    cout << "The new process could not be created. " << endl;
    return 1;
}
else
    for (int k = 0; k < 5; k++)
{
    if (pid == 0)     //pid zero from child
    {
         memoryptr->flag[0] = 1;     // set child flag true
         memoryptr->turn = 1;
    while (( memoryptr -> flag[1] ==1) && (memoryptr -> turn == 1))
         {     };

         // enter the critical section
         countB = memoryptr ->countA;
         countB = countB + 2;
         memoryptr->countA = countB;

         cout << "child" << '\t'
                 << countB << '\t'
                 << memoryptr->countA  << endl;

         memoryptr->flag [0] = 0;
         }

         else     // pid non zero from parent
         {
           memoryptr->flag[1] = 1;     // set flag to parent
           memoryptr->turn = 0;
           while (( memoryptr->flag[0] == 1) && (memoryptr->turn
== 0))
           {     };

           //enter critical section
           countB = memoryptr->countA;
           countB++;
           memoryptr->countA = countB;

           cout << "parent" << "\t"
                   << countB << "\t"
                   << memoryptr->countA <<endl;

           memoryptr->flag[1] = 0;     // set parent flag to
                             //false
         }
    }

 return 0;     // terminate with no error
}


