#if   !defined(__SEMAPHOREGROUP_HPP)
#define __SEMAPHOREGROUP_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(__SEMAPHORECOMMON_HPP)
#include <SemaphoreCommon.hpp>
#endif

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

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


namespace corelinux
{
  const Dword NAMEBUFFERSIZE(254);

  struct   SemaphoreReference
  {
    Int                  theCount;
    AbstractSemaphorePtr theSem;
  };

  CORELINUX_MAP( Index, SemaphoreReference, std::less<Index> ,  SemaphoreShares );

  DECLARE_CLASS( SemaphoreGroup );

  /**
     A SemaphoreGroup is an extension to the Linux semaphore set. 
     This provides a way to logically group semaphores. A SemaphoreGroup 
     acts as a Semaphore factory, creating and destroying Semaphores 
     for the user.
  */

  class SemaphoreGroup  : public Synchronized
  {
  public:

    /**
       Default constructor creates a private group 
       semaphores.
       @param Short Number of semaphores in group
       @param AccessRights Specifies access control for 
       group, default is owner only.
       @exception Assertion if aCount < 1 
       @exception SemaphoreException if kernel group 
       create call fails.
       @see corelinux::AccessRights
    */
                        
    SemaphoreGroup( Short , Int Rights = OWNER_ALL ) 
      throw(Assertion,SemaphoreException);

    /**
       Constructor to open or create a semaphore group with
       a specific identifier.
       @param  Short Number of semaphores in group,
       this only has meaning used if failOnExist = true
       @param SemaphoreGroupIdentifier valid group 
       identifier either through a system call or via 
       another ipc mechanism
       @param AccessRights Specifies access control for 
       group
       @param CreateDisposition indicates how to treat the 
       conditions that the group may meet in the request:
       CREATE_OR_REUSE indicates that the caller doesn't 
       care
       FAIL_IF_EXISTS indicates the attempt was for a create
       FAIL_IF_NOTEXISTS indicates the attempt was for a 
       open
       @exception Assertion if aCount < 1 
       @exception SemaphoreException for described states
       @see corelinux::AccessRights
    */

    SemaphoreGroup
    ( 
     Short,
     SemaphoreGroupIdentifierCref, 
     Int ,
     CreateDisposition disp=FAIL_IF_EXISTS
     ) throw(Assertion,SemaphoreException);

    /**
       Constructor to open or create a semaphore group by
       name.
       @param  Short Number of semaphores in group,
       this only has meaning used if failOnExist = true
       @param Char pointer to Group name
       @param AccessRights Specifies access control for 
       group
       @param CreateDisposition indicates how to treat the 
       conditions that the group may meet in the request:
       CREATE_OR_REUSE indicates that the caller doesn't 
       care
       FAIL_IF_EXISTS indicates the attempt was for a create
       FAIL_IF_NOTEXISTS indicates the attempt was for a 
       open
       @exception Assertion if aCount < 1 or
       aCount > system defined maximum for group
       @exception SemaphoreException for described states
       @see corelinux::AccessRights
    */

    SemaphoreGroup
    ( 
     Short,
     CharCptr, 
     Int ,
     CreateDisposition disp=FAIL_IF_EXISTS
     ) throw(Assertion,SemaphoreException);


    /// Virtual destructor

    virtual           ~SemaphoreGroup( void );

    //
    // Operator overloads
    //

    /**
       Equality operator compares the identifier
       @param SemaphoreGroup a reference to SemaphoreGroup
       @return bool True if equal
    */

    bool     operator==( SemaphoreGroupCref ) const;
    //
    // Accessors
    //
    /**
       Return the number of semaphores in the group
       @return Short Count
    */

    Short    getSemaphoreCount( void ) const;

    /**
       Return the SemaphoreGroupIdentifier
       @return SemaphoreGroupIdentifier 
    */

    inline   SemaphoreGroupIdentifierCref getIdentifier( void ) const
    {
      return theIdentifier;
    }

    //
    // Factory methods
    //

    /**
       Create a default semaphore type from group
       @return AbstractSemaphore aSem - pointer to created semaphore
       @exception SemaphoreException if no sems left in group
    */

    virtual  AbstractSemaphorePtr createSemaphore( void )
      throw( SemaphoreException ) = 0;

    /**
       Create or open (use) a specific semphore in the group
       @param SemaphoreIdentifier identifies which semphore id to
       create or attempt to use
       @param CreateDisposition indicates how to treat the conditions
       that the group may meet in the request:
       CREATE_OR_REUSE indicates that the caller doesn't care
       FAIL_IF_EXISTS indicates the attempt was for a create
       FAIL_IF_NOTEXISTS indicates the attempt was for a open
       @param Recursive to allow same thread multiple locks 
       @param Balking to allow the semaphore to balk
       @return AbstractSemaphore aSem - pointer to created or 
       opened semaphore
       @exception SemaphoreException if the disposition disagrees
       with the semaphore state, or if it is a erroneous identifier
    */

    virtual  AbstractSemaphorePtr createSemaphore
    ( 
     SemaphoreIdentifierRef aIdentifier,
     CreateDisposition disp = CREATE_OR_REUSE,
     bool Recursive=false, 
     bool Balking = false
     ) throw( SemaphoreException ) = 0;

    /**
       Create or open (use) a specific semphore in the group
       @param string identifies which semphore id to create or 
       attempt to use
       @param CreateDisposition indicates how to treat the conditions
       that the group may meet in the request:
       CREATE_OR_REUSE indicates that the caller doesn't care
       FAIL_IF_EXISTS indicates the attempt was for a create
       FAIL_IF_NOTEXISTS indicates the attempt was for a open
       @param Recursive to allow same thread multiple locks 
       @param Balking to allow the semaphore to balk
       @return AbstractSemaphore aSem - pointer to created or 
       opened semaphore
       @exception SemaphoreException if the disposition disagrees
       with the semaphore state, or if it is a erroneous identifier
    */


    virtual  AbstractSemaphorePtr createSemaphore
    ( 
     std::string aName,
     CreateDisposition disp = CREATE_OR_REUSE,
     bool Recursive=false, 
     bool Balking = false 
     ) throw( SemaphoreException ) = 0;

    /**
       Destroys a created semaphore from this group. 
       @param AbstractSemaphore pointer of semaphore to destroy
       @exception SemaphoreException if semaphore does not belong
       to this group
    */

    virtual  void  destroySemaphore( AbstractSemaphorePtr )
      throw( SemaphoreException ) = 0;
  protected:

    //
    // Constructors
    //
    /// Default constructor not allowed

    SemaphoreGroup( void ) throw( Assertion );

    /// Copy constructor not allowed

    SemaphoreGroup( SemaphoreGroupCref )
      throw( Assertion );

    //
    // Operator overloads
    //

    /// Assignment operator not allowed

    SemaphoreGroupRef operator=( SemaphoreGroupCref )
      throw( Assertion );

    //
    // Methods for shared control
    //

    /**
       This indirects to CSA for non-private group
       types
       @param Int reference to type where 0 = Mutex, 1 = Gateway,
       2 = Event, 3-10 reserved. Anything greater than 10 is
       user defined.
    */

    void  setGroupType( IntCref ) const;

    /**
       Claim an unused semaphore from the group. This implies
       that even though the group may be shared, the user has
       elected to use privately.
    */


    //
    // Methods for SemaphoreGroup base
    //

    /// Internal check for creation visibility

    inline   bool  isPrivate( void ) const
    {
      return (theGroupCSA == NULLPTR);
    }

  protected:

  private:

    friend   class SemaphoreCommon;

    /// The group identifier

    SemaphoreGroupIdentifier   theIdentifier;

    /// The number of semaphores in group

    Short    theNumberOfSemaphores;

    /// The CSA group descriptor

    CSAGrpHeaderPtr   theGroupCSA;

    /// The name if created with one, nullptr otherwise

    Char     theName[NAMEBUFFERSIZE];

  };
}

#endif // if !defined(__SEMAPHOREGROUP_HPP)

/*
   Common rcs information do not modify
   $Author: prudhomm $
   $Revision: 1.9 $
   $Date: 2000/08/31 22:52:20 $
   $Locker:  $
*/

