
/* x.cpp */
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <errno.h>
// #include <ncursesw/curses.h>
// #include <curses.h>
#define LOCK_SEMA   -1
#define UNLOCK_SEMA  1
#define KEY  1234567L     

static int semid = -1;


int printSemaValue(int line, const char *pStr) {

   int semVal0(0), semVal1(0);

   semVal0 = semctl (semid, 0, GETVAL);
   if (semVal0 < 0) {
      printf ("retcode < 0 from semct (%d, 0, GETVAL)\n\n", semid);
      return semVal0;
   }

   semVal1 = semctl (semid, 1, GETVAL);
   if (semVal1 < 0) {
      printf ("retcode < 0 from semct (%d, 1, GETVAL)\n\n", semid);
      return semVal1;
   }

   printf ("\n");
   // flash();

   printf ("semVal0 GETVAL %d\n", semVal0);
   // flash();

   printf ("semVal1 GETVAL %d\n%s, in Line %d\n", semVal1, pStr, line);
   // flash();

   return 1;

} 


static int init_semaphore (void) {

   int retCode(0);
   semid = semget (KEY, 0, IPC_PRIVATE);
   if (semid < 0) {
      semid = semget (KEY, 2, IPC_CREAT | IPC_EXCL | 0666);
      if (semid < 0) {
         printf ("\nretcode < 0 from semget\n");
         return semid;
      }
      printf ("\nsema %d created.\n\n", semid);
   }
   else
      printf ("\nSema %d already exists\n\n", semid);

   // flash();

   if (semctl (semid, 0, SETVAL, (int) 1) < 0) {
      printf ("\nretcode < 0 from semctl (%d, 0, SETVAL, 1)\n\n");
      return -1;
   }

   if (semctl (semid, 1, SETVAL, (int) 0) < 0) {
      printf ("\nretcode < 0 from semctl (%d, 0, SETVAL, 0)\n\n");
      return -3;
   }

   return 1;
}

static int semaOp (int op, int semNum) {
   struct sembuf semaphore;
   semaphore.sem_num = semNum;
   semaphore.sem_op  = op;
   semaphore.sem_flg = SEM_UNDO;
   if( semop (semid, &semaphore, 1) == -1) {
      return -1;
   }
   return 1;
}

int main (void) {
   long loop, res;

   res = init_semaphore ();
   if (res < 0) {
      printf ("\nretcode < 0 from init_semaphore\n");

      semctl(semid, 0, IPC_RMID, 0);

      return res;
   }

   printSemaValue(__LINE__, "After init_semaphore()");


   for (loop =0; loop<100000; ++loop) {

      printf ("\nloop = %ld\n", loop);

      // flash();

      res = semaOp (LOCK_SEMA, 0);
      if (res < 0) {
         int err = errno;
         if (err == ERANGE) {
            printf ("In Line %d: LOCK_SEMA 0 was not successful, errno = %d (ERANGE)\n", 
				__LINE__, errno);
         }
         else {
            printf ("In Line %d: LOCK_SEMA 0 was not successful, errno = %d\n", 
				__LINE__, errno);
         }
         
         break;
      }

      // usleep (3);

      res = semaOp (UNLOCK_SEMA, 1);

      if (res < 0) {
         int err = errno;
         if (err == ERANGE) {
            printf ("In Line %d: UNLOCK_SEMA 0 was not successful, errno = %d (ERANGE)\n", 				__LINE__, errno);
         }
         else {
            printf ("In Line %d: UNLOCK_SEMA 0 was not successful, errno = %d\n", 
			__LINE__, errno);
         }
   
         break;
      }

      printf ("\n");

   } // for ...

   // semctl(semid, 0, IPC_RMID, 0);

   return 1;
}

