Skip to content

File zoneheap.h

File List > cubrid > src > heaplayers > heaps > special > zoneheap.h

Go to the documentation of this file

/* -*- C++ -*- */

/*

  Heap Layers: An Extensible Memory Allocation Infrastructure

  Copyright (C) 2000-2020 by Emery Berger
  http://www.emeryberger.com
  emery@cs.umass.edu

  Heap Layers is distributed under the terms of the Apache 2.0 license.

  You may obtain a copy of the License at
  http://www.apache.org/licenses/LICENSE-2.0

*/

#ifndef HL_ZONEHEAP_H
#define HL_ZONEHEAP_H

#include <assert.h>

#include "utility/align.h"
#include "wrappers/mallocinfo.h"

namespace HL {

  template <class SuperHeap, size_t ChunkSize>
  class ZoneHeap : public SuperHeap {
  public:

    enum { Alignment = SuperHeap::Alignment };

    ZoneHeap()
      : _sizeRemaining (0),
    _currentArena (NULL),
    _pastArenas (NULL)
    {
      m_chkSize = ChunkSize;
    }

    ~ZoneHeap()
    {
      // printf ("deleting arenas!\n");
      // Delete all of our arenas.
      Arena * ptr = _pastArenas;
      while (ptr != NULL) {
    void * oldPtr = (void *) ptr;
    ptr = ptr->nextArena;
    //printf ("deleting %x\n", ptr);
    SuperHeap::free (oldPtr);
      }
      if (_currentArena != NULL)
    //printf ("deleting %x\n", _currentArena);
    SuperHeap::free ((void *) _currentArena);
    }

    inline void reset(const int chkSize)
    {
      m_chkSize = chkSize;
    }

    inline void * malloc (size_t sz) {
      void * ptr = zoneMalloc (sz);
      //      assert ((size_t) ptr % Alignment == 0);
      return ptr;
    }

    inline void free (void *) {}

    inline int remove (void *) { return 0; }


  private:

    int m_chkSize;

    ZoneHeap (const ZoneHeap&);
    ZoneHeap& operator=(const ZoneHeap&);

    inline void * zoneMalloc (size_t sz) {
      void * ptr;
      // Round up size to an aligned value.
      sz = HL::align<HL::MallocInfo::Alignment>(sz);
      // Get more space in our arena if there's not enough room in this one.
      if ((_currentArena == NULL) || (_sizeRemaining < sz)) {
    // First, add this arena to our past arena list.
    if (_currentArena != NULL) {
      _currentArena->nextArena = _pastArenas;
      _pastArenas = _currentArena;
    }
    // Now get more memory.
    size_t allocSize = m_chkSize;
    if (allocSize < sz) {
      allocSize = sz;
    }
    _currentArena =
      (Arena *) SuperHeap::malloc (allocSize + sizeof(Arena));
    if (_currentArena == NULL) {
      return NULL;
    }
    _currentArena->arenaSpace = (char *) (_currentArena + 1);
    _currentArena->nextArena = NULL;
    _sizeRemaining = allocSize;
      }
      // Bump the pointer and update the amount of memory remaining.
      _sizeRemaining -= sz;
      ptr = _currentArena->arenaSpace;
      _currentArena->arenaSpace += sz;
      assert (ptr != NULL);
      //      assert ((size_t) ptr % SuperHeap::Alignment == 0);
      return ptr;
    }

    class Arena {
    public:
      Arena() {
    static_assert((sizeof(Arena) % HL::MallocInfo::Alignment == 0),
              "Alignment must match Arena size.");
      }

      Arena * nextArena;
      char * arenaSpace;
    };

    size_t _sizeRemaining;

    Arena * _currentArena;

    Arena * _pastArenas;
  };

}

#endif