/****************************************************************************/
/* Copyright (c) 2000 MBARI                                                 */
/* MBARI Proprietary Information. All rights reserved.                      */
/****************************************************************************/
/* Summary  :                                                               */
/* Filename : Semaphore.cc                                                  */
/* Author   :                                                               */
/* Project  :                                                               */
/* Version  : 1.0                                                           */
/* Created  : 02/07/2000                                                    */
/* Modified :                                                               */
/* Archived :                                                               */
/****************************************************************************/
/* Modification History:                                                    */
/****************************************************************************/
#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 "SemaphoreP.h"


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

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

     init( semName );

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

int Semaphore::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("Semaphore::Semaphore() - 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("Semaphore::Semaphore() - 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("Semaphore::Semaphore() - mmap()");
    exit(1);
  }

  close(fd);

  return 0;
}


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


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


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



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


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


