#if   !defined(__GATEWAYSEMAPHORE_HPP)
#define __GATEWAYSEMAPHORE_HPP

/*
  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(__SEMAPHORE_HPP)
#include <Semaphore.hpp>
#endif

#if   !defined(__MAP_HPP)
#include <Map.hpp>
#endif

namespace corelinux
{
   DECLARE_CLASS( GatewaySemaphore );

   CORELINUX_MAP
      ( 
         ThreadIdentifier, 
         Count , 
         std::less<ThreadIdentifier>,
	 GatewayClient
      );

   /**
   GatewaySemphore enables a depth of resource indicator. 
   Unlike the tradition boolean semaphore (locked,unlocked), 
   this type assumes a finite number of threads/processes can be 
   granted access up to theResourceMaximum.
   The semantics regarding semaphore and recursion in relationship
   to the GatewaySemaphore is as follows:
   <p>
   With recursion enabled:
   <ul>
   <li><b>Semaphore::getOwningThreadIdentifier</b> returns the ThreadIdentifier
   of the thread that pushed the value to zero(0).
   <li><b>Semaphore::getRecursionQueueLength</b> returns the depth of recursion
   by <b>Semaphore::getOwningThreadIdentifier</b>
   <li><b>GatewaySemaphore::isAnOwner</b> returns true if the current 
   thread is in the set of threads that own a resource.
   <li><b>GatewaySemaphore::getOwnerRecursionQueueLength</b> returns either
   -1 if the current thread does not control a resource, 0 if the current thread
   does own a resource, but has not recursed, or returns the depth of recursion
   for the calling thread. 
   </ul>
   
   */

   class GatewaySemaphore : public Semaphore
   {
   public:

      //
      // Constructors and destructors
      //

                        /**
                        Default constructor requires the identifier
                        of the semaphore in the semaphore group and
                        a count of resources for control
                        @param SemaphoreGroupPtr The owning SemaphoreGroup 
                        @param SemaphoreIdentifier The identifier
                        for the Semaphore from the SemaphoreGroup
                        @param Count number of resources the semaphore 
                        controls
                        @param bool true if recursion enabled
                        @param bool true if balking enabled
                        */
                  
                        GatewaySemaphore
                           ( 
                              SemaphoreGroupPtr,
                              SemaphoreIdentifierRef,
                              Count ,
                              bool  Recursive = false,
                              bool  Balking = false
                           ) throw ( NullPointerException );

                        /// Virtual Destructor

      virtual           ~GatewaySemaphore( void );

      //
      // Accessors
      //

               /// Ask if AbstractSemaphore instance is locked
      
      virtual  bool isLocked( void );

               /// Returns true if calling thread owns a resource

      virtual  bool  isAnOwner( void );

               /**
               Returns the recursion depth for the calling thread
               @return Counter -1 if not an owner, 0 if owner but not
               recursed, or > 0 for recursion depth.
               */

      virtual  Counter  getOwnerRecursionQueueLength( void );


      //
      // Mutators
      //
         
               /// Request the lock, wait for availability
      
      virtual  SemaphoreOperationStatus lockWithWait(void)
                  throw( SemaphoreException );

               /// Request the lock without waiting
      
      virtual  SemaphoreOperationStatus lockWithNoWait(void)
                  throw( SemaphoreException );


               /// Request the AbstractSemaphore but timeout if not available
      
      //      virtual  SemaphoreOperationStatus   lockWithTimeOut( Timer )
      //                   throw(SemaphoreException) = 0;
      
               /// Release the lock
      
      virtual  SemaphoreOperationStatus release(void)
                  throw( SemaphoreException );

   protected:

      //
      // Constructors
      //
                           /// Default construct throws assert

                           GatewaySemaphore( void ) throw( Assertion );

                           /// Copy constructor throws assertion

                           GatewaySemaphore( GatewaySemaphoreCref ) 
                              throw( Assertion );

      //
      // Operator overloads
      //
               /// Assignment operator throws assertion

               GatewaySemaphoreRef operator=( GatewaySemaphoreCref ) 
                              throw( Assertion );

      //
      // Mutators
      //

               SemaphoreOperationStatus lockAndAdd
                  ( 
                     ThreadIdentifierRef aTid, 
                     Int aFlag = 0 
                  );


   private:

               /// The maximum count value

               Count          theMaxCount;

               /// Set of threads that hold

               GatewayClient  theClients;

   };
}

#endif // if !defined(__GATEWAYSEMAPHORE_HPP)
/*
   Common rcs information do not modify
   $Author: prudhomm $
   $Revision: 1.4 $
   $Date: 2000/08/31 22:52:20 $
   $Locker:  $
*/

