2005/5/9

     
 

BitmapPagedAllocator.h

artefaktur
// -*- mode:C++; tab-width:2; c-basic-offset:2; indent-tabs-mode:nil -*- 
//
// Copyright (C) 2000-2005 by Roger Rene Kommer / artefaktur, Kassel, Germany.
// 
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Library General Public License (LGPL).
// 
// 
// This 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 
// License ACDK-FreeLicense document enclosed in the distribution
// for more for more details.
// This file is part of the Artefaktur Component Development Kit:
//                         ACDK
// 
// Please refer to
// - http://www.acdk.de
// - http://www.artefaktur.com
// - http://acdk.sourceforge.net
// for more information.
// 
// $Header: /cvsroot/acdk/acdk/acdk_core/src/acdk/lang/sys/BitmapPagedAllocator.h,v 1.13 2005/02/05 10:45:00 kommer Exp $
#ifndef acdk_lang_sys_BitmapPagedAllocator_h
#define acdk_lang_sys_BitmapPagedAllocator_h

#include "core_mutex.h"
#include "core_fastmutex.h"
#include "ObjectLockPool.h"
#include "SysRefHolder.h"

namespace acdk {
namespace lang {
namespace sys {


  
ACDK_DECL_SYS_CLASS(BitmapPagedAllocator);

/*
Sizes of BitmapPage
32, 64, 128, 256, 512, 1024, 2048
*/

class BitmapPagedAllocator;

template <int SlotSize>
class ACDK_CORE_PUBLIC BitmapPage
{
  /** next page */
  
  BitmapPage<SlotSize>* _next;
  BitmapPagedAllocator* _allocator;
  int _bitmap;
  int _slotSize;
  char _data[32][SlotSize + sizeof(BitmapPage<SlotSize>*) /*+ sizeof(int)*/];
  //BitmapPageSlot<SlotSize> _slots[32];
  /*
    char data[]
    int idx;
    BitmapPage*   
  */
public:  
  BitmapPage(BitmapPagedAllocator* allocator, BitmapPage<SlotSize>* prev)
  : _next(0),
    _allocator(allocator),
    _slotSize(SlotSize)
  {
    if (prev)
      prev->_next = this;
    memset((void*)&_bitmap, 0, sizeof(_bitmap));
    memset(_data, 0, sizeof(_data));
    for (int i = 0; i < 32; i++) 
    {
      char* ptr = (char*)&_data[i][0];
      *((BitmapPage<SlotSize>**)ptr) = this;
    }
    //BitmapPage<SlotSize>** mp = (BitmapPage<SlotSize>**)&_data[1][0];
  }
  char* getFreeSlot()
  {
    int idx = getFreeIndex();
    if (idx == -1) 
    {
      if (_next == 0)
        _next = new BitmapPage<SlotSize>(_allocator, this);
      return _next->getFreeSlot();
    }
    int sls = SlotSize;
    // debuggin
    //BitmapPage<SlotSize>** mp = (BitmapPage<SlotSize>**)&_data[idx][0];
    return (char*)_data[idx] + ALIGNEDSIZEOF(BitmapPage<SlotSize>**);// + ALIGNEDSIZEOF(int);
  }
  int getFreeIndex()
  {
    if (_bitmap == -1) 
      return -1;
    int tbm = _bitmap;
    int offset = 0;
    unsigned short serg;
    if ((unsigned short)_bitmap != 0xFFFF) 
      serg = (unsigned short)_bitmap;
    else {
      serg = _bitmap >> 16;
      offset += 16;
    }
    unsigned char berg;
    if ((unsigned char)serg != 0xFF) 
      berg = (unsigned char)serg;
    else {
      berg = serg >> 8;
      offset += 8;
    }
    int nmask = 1;
    for (int i = 0; i < 8; i++) 
    {
      if (~berg & nmask) {
        offset += i;
        int mask = 1;
        mask <<= offset;
        _bitmap |= mask;
        return offset;
      }
      nmask <<= 1;
    }
    return -1;
  }
  bool releaseSlot(char* ptr)
  {
    int diff = (ptr - sizeof(BitmapPage<SlotSize>*) - (char*)&_data[0][0]);
    int idx = diff / (_slotSize + sizeof(BitmapPage<SlotSize>*));
    int nmask = 1;
    nmask <<= idx;
    _bitmap &= ~nmask;
    return _bitmap == 0;
  }
};

class ACDK_CORE_PUBLIC RawPage
{
private:
  BitmapPagedAllocator* _allocator;
  RawPage* _next;
  RawPage* _prev;
  char* _data;
public:
  RawPage(BitmapPagedAllocator* allocator, int size, RawPage* prev)
  : _allocator(allocator),
    _next(0),  
    _prev(prev),
    _data(0)
  {
    if (_prev)
      _prev->_next = this;
    _data = new char[size];
  }
  ~RawPage()
  {
    if (_data != 0)
      delete _data;
    _data = 0;
  }
  void flush()
  {
    if (_next != 0)
      _next->flush();
    delete this;
  }
  char* data() { return _data; }
};

foreign
class ACDK_CORE_PUBLIC  BitmapPagedAllocator
:  public AbstractAllocator
{
protected:
  
  BitmapPage<32>* _page32;
  BitmapPage<64>* _page64;
  BitmapPage<128>* _page128;
  BitmapPage<512>* _page512;
  BitmapPage<1024>* _page1024;
  BitmapPage<2048>* _page2048;
  RawPage* _rawPagesFirst;
  RawPage* _rawPagesLast;
public: 
  BitmapPagedAllocator()
    : AbstractAllocator(StandardAllocatorType, "BitmapPagedAllocator"),
      _rawPagesFirst(0),
      _rawPagesLast(0)
  {
    _page32 = new BitmapPage<32>(this, 0);
    _page64 = new BitmapPage<64>(this, 0);
    _page128 = new BitmapPage<128>(this, 0);
    _page512 = new BitmapPage<512>(this, 0);
    _page1024 = new BitmapPage<1024>(this, 0);
    _page2048 = new BitmapPage<2048>(this, 0);
  }
  virtual ~BitmapPagedAllocator();
// Allocator
  virtual void* allocate(size_t size, AllocatedType at = RawMem)
  {
    if (size < 512) {
      if (size < 64) {
        if (size < 32)
          return _page32->getFreeSlot();
        else
          return _page64->getFreeSlot();
      } else {
        if (size < 128)
          return _page128->getFreeSlot();
        else
          return _page512->getFreeSlot();
      }
    } else {
      if (size < 2048) {
        if (size < 1024)
          return _page1024->getFreeSlot();
        else
          return _page2048->getFreeSlot();
      } else {
        if (_rawPagesFirst == 0) {
          _rawPagesFirst = new RawPage(this, size, 0);
          _rawPagesLast = _rawPagesFirst;  
        } else {
          _rawPagesLast = new RawPage(this, size, _rawPagesLast);
        }
        return _rawPagesLast->data();
      }
    }
  }
  virtual void deallocate(void* ptr, AllocatedType at = RawMem)
  {
    void *realptr = ((char*)ptr) - ALIGNEDSIZEOF(::acdk::lang::sys::BitmapPage<1>**);
    ::acdk::lang::sys::BitmapPage<1>** bm = (::acdk::lang::sys::BitmapPage<1>**)realptr;
    (*bm)->releaseSlot((char*)ptr);
  }
  //virtual void* allocateObject(size_t size);
  //virtual void deallocateObject(void* ptr);
  virtual void* raw_allocate(size_t size, AllocatedType type)
  {
    return allocate(size);
  }
  virtual void raw_deallocate(size_t size, void* ptr, AllocatedType type)
  {
    deallocate(ptr);
  }
  virtual void listObjects(::acdk::lang::ref::NotifyObjectEventListener* listener, int flags);
  
  
  
};


class ACDK_CORE_PUBLIC BitmapPagedHeap
:  public HeapFrame 
{
protected:
  RBitmapPagedAllocator _allocator;  
public:
  
  BitmapPagedHeap(int pagesize = 1024, RHeapFrame top = 0, int flags = HeapIsThread, const char* name = "");
  virtual bool onDestroy(acdk::lang::Object* obj); 
  virtual bool gc(bool recursiv = true);
  virtual Allocator* allocator() { return _allocator.getImpl(); }
  virtual void listObjects(::acdk::lang::ref::NotifyObjectEventListener* listener, int flags);
};


} // namespace sys
} // namespace lang 
} // namespace acdk 
#endif //acdk_lang_sys_BitmapPagedAllocator_h