//=========================================================================
// Summary  : */
// Filename : Semaphore.cc
// Author   : */
// Project  : */
// Revision : 1
// Created  : 2000/08/19
// Modified : 2000/08/19
//=========================================================================
// Description :
//=========================================================================
#include <fcntl.h>
#include <errno.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <malloc.h>
#include <sys/mman.h>
#include <sys/types.h>
#include "Semaphore.h"


auvSemaphore::auvSemaphore(const char *semName)
{
     init( semName );
}

auvSemaphore::auvSemaphore(const char *semName, int initialValue)
{

     init( semName );

     if (sem_init(_semaphore, 1, initialValue) == -1) {
	  perror("auvSemaphore::auvSemaphore() - sem_init()");
	  exit(1);
     }
}

int auvSemaphore::init( const char *semName )
{
  _name = strdup(semName);

  int shmFlags = O_CREAT | O_RDWR;
  int mmapProtect = PROT_READ | PROT_WRITE;

  // Get shared memory file descriptor
  int fd;
  if ((fd = shm_open(name(), shmFlags, 0777)) == -1) {
    perror("auvSemaphore::auvSemaphore() - shm_open()");
    exit(1);
  }

  // Set size of shared memory segment
  if (ltrunc(fd, sizeof(sem_t), SEEK_SET) == -1) {
    /* If errno is EBUSY, it means someone else has already set the
       size, and that's fine. Otherwise, there's a serious problem. */
    if (errno != EBUSY) {
      perror("auvSemaphore::auvSemaphore() - ltrunc()");
      exit(1);
    }
  }

  // Map the shared memory
  _semaphore = (sem_t *)mmap(0, sizeof(sem_t), mmapProtect, MAP_SHARED, fd, 0);
  if (_semaphore == (sem_t *)-1) {
    perror("auvSemaphore::auvSemaphore() - mmap()");
    exit(1);
  }

  close(fd);

  return 0;
}


auvSemaphore::~auvSemaphore()
{
  free((void *)_name);
  sem_destroy(_semaphore);
}


const char *auvSemaphore::name()
{
  return _name;
}


int auvSemaphore::post()
{
  return sem_post(_semaphore);
}



int auvSemaphore::wait()
{
  return sem_wait(_semaphore);
}


int auvSemaphore::tryWait()
{
  return sem_trywait(_semaphore);
}


