//=========================================================
//  MusE
//  Linux Music Editor
//  $Id: memory.h,v 1.1.1.1 2003/10/29 10:05:18 wschweer Exp $
//
//  (C) Copyright 2003 Werner Schweer (ws@seh.de)
//=========================================================

#ifndef __MEMORY_H__
#define __MEMORY_H__

#include <stdio.h>
#include <map>

// most of the following code is based on examples
// from Bjarne Stroustrup: Die C++ Programmiersprache

//---------------------------------------------------------
//   Pool
//---------------------------------------------------------

class Pool {
      struct Verweis {
            Verweis* next;
            };
      struct Chunk {
            enum { size = 4 * 1024 };
            Chunk* next;
            char mem[size];
            };
      enum { dimension = 8 };
      Chunk* chunks[dimension];
      Verweis* head[dimension];
      Pool(Pool&);
      void operator=(Pool&);
      void grow(int idx);

   public:
      Pool();
      ~Pool();
      void* alloc(size_t n);
      void free(void* b, size_t n);
      };

//---------------------------------------------------------
//   alloc
//---------------------------------------------------------

inline void* Pool::alloc(size_t n)
      {
      int idx = ((n + sizeof(int) - 1) / sizeof(int)) - 1;
      if (idx >= dimension) {
            printf("panic: alloc %d\n", n);
            exit(-1);
            }
      if (head[idx] == 0)
            grow(idx);
      Verweis* p = head[idx];
      head[idx] = p->next;
      return p;
      }

//---------------------------------------------------------
//   free
//---------------------------------------------------------

inline void Pool::free(void* b, size_t n)
      {
      int idx = ((n + sizeof(int) - 1) / sizeof(int)) - 1;
      if (idx >= dimension) {
            printf("panic: alloc %d\n", n);
            exit(-1);
            }
      Verweis* p = static_cast<Verweis*>(b);
      p->next = head[idx];
      head[idx] = p;
      }

extern Pool midiRTmemoryPool;

//---------------------------------------------------------
//   RTalloc
//---------------------------------------------------------

template <class T> class RTalloc
      {
   public:
      typedef T         value_type;
      typedef size_t    size_type;
      typedef ptrdiff_t difference_type;

      typedef T*        pointer;
      typedef const T*  const_pointer;

      typedef T&        reference;
      typedef const T&  const_reference;

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

      RTalloc();
      template <class U> RTalloc(const RTalloc<U>&) {}
      ~RTalloc() {}

      pointer allocate(size_type n, void * = 0) {
            return static_cast<T*>(midiRTmemoryPool.alloc(n * sizeof(T)));
            }
      void deallocate(pointer p, size_type n) {
            midiRTmemoryPool.free(p, n * sizeof(T));
            }

      RTalloc<T>&  operator=(const RTalloc&) { return *this; }
      void construct(pointer p, const T& val) {
            new ((T*) p) T(val);
            }
      void destroy(pointer p) {
            p->~T();
            }
      size_type max_size() const { return size_t(-1); }

      template <class U> struct rebind { typedef RTalloc<U> other; };
      template <class U> RTalloc& operator=(const RTalloc<U>&) { return *this; }
      };

template <class T> RTalloc<T>::RTalloc() {}

#endif

