#if !defined(__ABSTRACTALLOCATOR_HPP)
#define  __ABSTRACTALLOCATOR_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(__ALLOCATOR_HPP)
#include <Allocator.hpp>
#endif

namespace corelinux
{
   /**
   AbstractAllocator is a abstract template which provides for the 
   extension of memory managment on a TypeImpl object
   by TypeImpl object basis. The derivation needs to
   implement the allocateObject and deallocateObject mutators
   for memory management.
   @see Allocator, AbstractFactory
   */

   template< class TypeImpl >
      class AbstractAllocator : public Allocator
      {
      public:

         //
         // Constructors and destructor
         //

                           /// Default constructor
                           
                           AbstractAllocator( void )
                              :
                              Allocator( )
                           {
                              ;  // do nothing
                           }

                           /**
                           Copy constructor
                           @param AbstractAllocator const reference
                           */

                           AbstractAllocator
                              ( 
                                 const AbstractAllocator & aRef 
                              )
                              :
                              Allocator( aRef )
                           {
                              ;  // do nothing
                           }

                           /// Virtual destructor

         virtual           ~AbstractAllocator( void )
                           {
                              ;  // do nothing
                           }

         //
         // Operator overloads
         //
   
                  /**
                  Assingment operator overload
                  @param AbstractAllocator const reference
                  @return AbstractAllocator reference to self
                  */

                  AbstractAllocator & operator=
                     ( 
                        const AbstractAllocator & aRef 
                     )
                  {
                     Allocator::operator=(aRef);
                     return (*this);
                  }

                  /**
                  Equality operator overload
                  @param AbstractAllocator const reference
                  @return true if same identity
                  */

                  bool  operator==( const AbstractAllocator & aRef ) const
                  {
                     return Allocator::operator==(aRef);
                  }


         //
         // Factory methods
         //

                  /**
                  Create type will invoke the allocateObject
                  method of the derivation and will increment
                  the number of allocations. In the event of
                  any exception, the allocation count will
                  be adjusted.
                  @return TypeImpl pointer
                  @exception any
                  */

                  TypeImpl    *createType( void ) 
                  {
                     TypeImpl *aPtr( NULLPTR );
                     try
                     {
                        aPtr = allocateObject();
                        incrementAllocates();
                     }
                     catch( ... )
                     {
                        decrementAllocates();
                        throw;
                     }
                     return aPtr;
                  }

                  /**
                  Destroy type will invoke the deallocateObject
                  method of the derivation and will increment
                  the number of deallocation. In the event of
                  any exception, the deallocation count will be
                  adjusted
                  @param TypeImpl pointer
                  @exception any
                  */

                  void  destroyType( TypeImpl *aPtr ) 
                  {
                     try
                     {
                        deallocateObject( aPtr );
                        incrementDeallocates();
                     }
                     catch( ... )
                     {
                        decrementDeallocates();
                        throw;
                     }
                  }
                  
      protected:

         //
         // Factory virtual declarations
         //

                  /**
                  allocates a object in the subclass
                  @return TypeImpl pointer
                  */

         virtual  TypeImpl *allocateObject( void ) = 0;

                  /**
                  de-allocates a object in the subclass
                  @param TypeImpl pointer
                  */

         virtual  void     deallocateObject( TypeImpl * ) = 0;


      };

}

/**
CORELINUX_DEFAULT_ALLOCATOR macro defines a class for default
allocation, using global 'new' and 'delete'.
@param nameTag - the name for the default class
@param typeTag - the type class for the template expansion
*/

#define  CORELINUX_DEFAULT_ALLOCATOR( nameTag, typeTag )          \
   class nameTag : public CORELINUX(AbstractAllocator<typeTag>)   \
   {                                                              \
   public:                                                        \
                        nameTag( void )                           \
                           :                                      \
                           CORELINUX(AbstractAllocator<typeTag>)()\
                        {                                         \
                           ;                                      \
                        }                                         \
                                                                  \
      virtual           ~nameTag( void )                          \
                        {                                         \
                           ;                                      \
                        }                                         \
   protected:                                                     \
                                                                  \
                                                                  \
      virtual  typeTag  *allocateObject( void )                   \
               {                                                  \
                  return ::new typeTag;                           \
               }                                                  \
                                                                  \
      virtual  void     deallocateObject( typeTag *aPtr )         \
      {                                                           \
         ::delete aPtr;                                           \
      }                                                           \
   };                                                             \
typedef nameTag *       nameTag ## Ptr;                           \
typedef const nameTag * nameTag ## Cptr;                          \
typedef nameTag &       nameTag ## Ref;                           \
typedef const nameTag & nameTag ## Cref;

#endif   // if !defined(__ABSTRACTALLOCATOR_HPP)

/*
   Common rcs information do not modify
   $Author: prudhomm $
   $Revision: 1.2 $
   $Date: 2001/02/15 16:34:05 $
   $Locker:  $
*/

