
/*
  CoreLinux++ 
  Copyright (C) 1999,2000 CoreLinux Consortium
  
   The CoreLinux++ Library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Library General Public License as
   published by the Free Software Foundation; either version 2 of the
   License, or (at your option) any later version.

   The CoreLinux++ Library Library is distributed in the hope that it will 
   be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   Library General Public License for more details.

   You should have received a copy of the GNU Library General Public
   License along with the GNU C Library; see the file COPYING.LIB.  If not,
   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
   Boston, MA 02111-1307, USA.  
*/

#if   !defined(__COMMON_HPP)
#include <Common.hpp>
#endif

#if   !defined(__SCALARIDENTIFIERS_HPP)
#include <ScalarIdentifiers.hpp>          // Various identifiers
#endif

#if   !defined(__ABSTRACTSEMAPHORE_HPP)
#include <AbstractSemaphore.hpp>
#endif

#if   !defined(__SEMAPHOREGROUP_HPP)
#include <SemaphoreGroup.hpp>
#endif

#if   !defined(__SEMAPHORECOMMON_HPP)
#include <SemaphoreCommon.hpp>
#endif

extern "C"
{
   #include <sys/sem.h>
   #include <errno.h>
}

#ifdef _SEM_SEMUN_UNDEFINED
union semun {
   int val;
   struct semid_ds *buf;
   unsigned short int *array;
   struct seminfo *__buf;
}; 
#endif

namespace corelinux
{
   //
   // Default constructor
   //

   AbstractSemaphore::AbstractSemaphore
      ( 
         SemaphoreGroupPtr aGroup,
         SemaphoreIdentifierRef aSemId
      ) 
      throw ( NullPointerException )
      :
      Synchronized(),
      theGroup( aGroup ),
      theSemIdentifier( aSemId )
   {
      if( theGroup == NULLPTR )
      {
         throw NullPointerException(LOCATION);
      }
      else
      {
         SemaphoreGroupIdentifier   aId( aGroup->getIdentifier() );
         theGroupIdentifier = (Int) aId;
      }
   }

   //
   // Copy constructor not allowed
   //

   AbstractSemaphore::AbstractSemaphore( AbstractSemaphoreCref ) 
      throw(Assertion)
      :
      Synchronized()
   {
      NEVER_GET_HERE;
   }

   //
   // Virtual Destructor
   //

   AbstractSemaphore::~AbstractSemaphore( void )
   {
      ;  // do nothing
   }

   // Get the group identifier

   SemaphoreGroupIdentifierCref  AbstractSemaphore::getGroupIdentifier( void ) const
   {
      return theGroup->getIdentifier();
   }

   SemaphoreIdentifierCref AbstractSemaphore::getIdentifier( void ) const 
   {
      return theSemIdentifier;
   }

   // Get the initial value for the semaphore if we can

   Int   AbstractSemaphore::getInitialValue( void )
   {
      return SemaphoreCommon::getSemaphoreMaxValue( theGroup, getId() );
   }

   //
   // Retrieve the current value for the semaphore, this
   // can always be returned without checking shared status
   //

   Int   AbstractSemaphore::getValue( void )
   {
      union semun aSemun;

      aSemun.val = 0;
      return semctl( getGroupId(), 
                     getId().getScalar(), 
                     GETVAL, 
                     aSemun);
   }

   //
   // Use by derivations to attempt control at zero. Here we
   // must pass through the common area to insure we are
   // updating csa
   //

   SemaphoreOperationStatus   AbstractSemaphore::setLock( Int aFlag )
   {
      int ks( SemaphoreCommon::setLock
              ( 
                 theGroup, 
                 getGroupId(), 
                 getId(), 
                 aFlag 
               )
            );

      return (SemaphoreOperationStatus)
         ( ks < 0 ? ( Thread::getKernelError() == EAGAIN ? UNAVAILABLE : ks ) : ks );
   }

   //
   // Use by derivations to release control. As with lock and setValue, we
   // pass through to common access
   //

   SemaphoreOperationStatus   AbstractSemaphore::setUnlock( Int aFlag )
   {
      return (SemaphoreOperationStatus) 
         SemaphoreCommon::setUnLock
            (
               theGroup,
               getGroupId(),
               getId(),
               aFlag
            );
   }

   //
   // Use by derivations to release control. As with lock and setValue, we
   // pass through to common access
   //

   SemaphoreOperationStatus   AbstractSemaphore::waitZero( Int aFlag )
   {
      return (SemaphoreOperationStatus) 
         SemaphoreCommon::waitZero
            (
               theGroup,
               getGroupId(),
               getId(),
               aFlag
            );
   }

   //
   // Sets the value of the semaphore
   //

   SemaphoreOperationStatus   AbstractSemaphore::setValue( Int aValue )
   {
      return (SemaphoreOperationStatus) 
         SemaphoreCommon::setMaxValue
            (
               theGroup, 
               getId(), 
               aValue 
            );
   }
}


/*
   Common rcs information do not modify
   $Author: dulimart $
   $Revision: 1.7 $
   $Date: 2000/09/09 07:06:17 $
   $Locker:  $
*/




