#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h> 
#include <sys/shm.h> 

/* using namespace std */
#define PERMS 0666

#define BUFFER_SIZE 10

struct share_mem {
	char buffer[BUFFER_SIZE];
	int in;
	int out;
} item;

void producer (struct share_mem *shareptr) {
	char nextProduced;

	for (nextProduced = 'a'; nextProduced <= 'z'; nextProduced++) {
		/* produce an item in nextProduced */
		while (((shareptr->in + 1) % BUFFER_SIZE) == shareptr->out)
			; /* do nothing */

		printf ("Produce: %c\n", nextProduced);
		
		shareptr->buffer[shareptr->in] = nextProduced;
		shareptr->in = (shareptr->in + 1) % BUFFER_SIZE;
	}
}

void consumer (struct share_mem *shareptr) {
	char nextConsumed;

	while (nextConsumed != 'z') {
		while (shareptr->in == shareptr->out)
			; /* do nothing */

		nextConsumed = shareptr->buffer[shareptr->out];
		shareptr->out = (shareptr->out + 1) % BUFFER_SIZE;
		/* consume the item in nextConsumed */

		printf ("Consume: %c\n", nextConsumed);
	}
}

main (int argc, char *argv[]) {
	int shmid;
	int pid;
	struct share_mem *shareptr;

	shmid = shmget((key_t)IPC_PRIVATE, sizeof(struct share_mem), PERMS | IPC_CREAT);
	if (shmid < 0) {
		fprintf (stderr, "shared memory creation failed\n");
		exit (-1);
	}

	/* fork another process */
	pid = fork();

	if (pid < 0) { /* error occurred */
		fprintf (stderr, "Fork Failed\n");
		exit (-1);
	}

	if ((shareptr = (struct share_mem *) shmat(shmid, 0, 0)) == (struct share_mem *) -1) {
		fprintf (stderr, "can't attach to shared memory\n");
		exit (-1);
	}
	
	shareptr->in = 0;
	shareptr->out = 0;

	if (pid == 0) { /* child process */
		consumer(shareptr);
	} else { /* parent process */
		producer(shareptr);
	}

	if (shmdt(shareptr) < 0) {
		fprintf (stderr, "child detach failed\n");
		exit (-1);
	}

	if (pid != 0) {
		if (shmctl(shmid, IPC_RMID, 0) < 0) {
			fprintf (stderr, "remove of shared memory failed\n");
			exit (-1);
		}
	}
}
