//
//	File:		    astl_allocator.h
//  Version:    ASTL 1.1
//	Copyright:	Vincent LE MAOUT
//	Date:		    Wed Dec 2 15:50:07 MET 1998
//	Descrition:	defines  templates allocator_interface encapsulating 
//              objects implementing allocators (allocator_implementation_simple and 
//              allocator_implementation_register) + default_allocator
//              

#ifndef ASTL_ALLOCATORS
#define ASTL_ALLOCATORS

#include <memory>
#include <iostream>

  // Generic allocator INTERFACE:
  
  template <class T, class Allocator_implementation>
    class allocator_interface
    {
    protected:
      Allocator_implementation implementation;

    public:
      typedef T         value_type;
      typedef T&        reference;
      typedef const T&  const_reference;
      typedef T*        pointer;
      typedef const T*  const_pointer;
      typedef size_t    size_type;
      typedef ptrdiff_t difference_type;
  
      allocator_interface(Allocator_implementation x = Allocator_implementation())
	: implementation(x)
      { }

      pointer address(reference x) const {
	return (&x);
      }
  
      const_pointer address(const_reference x) const {
	return (&x);
      }

#ifdef WIN32
      pointer allocate(size_type n, const void *) {
	return (pointer(implementation.allocate(n * sizeof(T))));
      }

      void deallocate(pointer p, size_type n) {
	implementation.deallocate(p, n);
      }

      char _FARQ *_Charalloc(size_type n) {
	return ((char _FARQ *) implementation.allocate(n));
      }
      
      void construct(pointer p, const_reference x) {
	_Construct(p, x);
      }

      void destroy(pointer p) {
	_Destroy(p);
      }

#else
      pointer allocate(size_type n = 1) {
	return (pointer(implementation.allocate(n * sizeof(T))));
      }

      void deallocate(pointer p, size_type n) {
	implementation.deallocate(p, n);
      }

      void construct(pointer p, const_reference x) {
	::construct(p, x);
      }
      
      void destroy(pointer p) {
	::destroy(p);
      }
#endif // WIN32
    };
  
      // simple new/delete allocator IMPLEMENTATION:
  
      class allocator_implementation_simple
      {
      public:
	static void* allocate(size_t n) {
	  return (::new char[n]);
	}
    
	static void deallocate(void *p, size_t) {
	  ::delete p;
	}
      };
    
      // allocator IMPLEMENTATION keeping tracks of all allocations/deallocations:
  
      class allocator_implementation_register
      {
      public:

#ifdef WIN32
  static unsigned long bytes_allocated, bytes_freed;
  static unsigned long calls_to_allocate, calls_to_deallocate;
#else
	static long long bytes_allocated, bytes_freed;
	static long long calls_to_allocate, calls_to_deallocate;
#endif  // WIN32
  
	static void* allocate(size_t n) {
	  ++calls_to_allocate;
	  bytes_allocated += n;
	  return (::new char[n]);
	}
    
	static void deallocate(void *p, size_t n) {
	  ++calls_to_deallocate;
	  bytes_freed += n;
	  ::delete [] p;
	}
    
	static void stats(ostream &out = cout) 
	{
	  out << "bytes allocated     " << allocator_implementation_register::bytes_allocated 
	      << endl
	      << "bytes freed         " << allocator_implementation_register::bytes_freed 
	      << endl
	      << "calls to allocate   " << allocator_implementation_register::calls_to_allocate 
	      << endl
	      << "calls to deallocate " << allocator_implementation_register::calls_to_deallocate 
	      << endl;
	}
    
      };
  
#ifdef WIN32
      unsigned long allocator_implementation_register::bytes_allocated     = 0;
      unsigned long allocator_implementation_register::bytes_freed         = 0;
      unsigned long allocator_implementation_register::calls_to_allocate   = 0;
      unsigned long allocator_implementation_register::calls_to_deallocate = 0;
#else
      long long allocator_implementation_register::bytes_allocated     = 0;
      long long allocator_implementation_register::bytes_freed         = 0;
      long long allocator_implementation_register::calls_to_allocate   = 0;
      long long allocator_implementation_register::calls_to_deallocate = 0;
#endif // WIN32

#endif // ASTL_ALLOCATORS





  
