元派遣プログラマの自称技術系ブログです。雑記とか自作のオープンソースプロジェクトの話とか。
Javaとか組込とかできます。お仕事ください。

なんちゃってメモリマネージャ

マイコンだと、基本的にメモリマネージャないですよね。でも小規模なメモリマネージャはあってもいいかな?ということで、配列要素を使うメモリマネージャ作りました。

このメモリマネージャは、スタック、又は静的に確保した固定長の配列要素を、動的に割り当てます。最大要素数は32個なので、あまり大規模には使えません。

/*lpcstd*/
typedef short NyLPC_TInt16;
typedef long NyLPC_TInt32;
typedef long NyLPC_TUInt32;
#define NyLPC_ASSERT(e) if(!(e)){printf("ギャー\n");}
#define NyLPC_ABORT() {printf("フギャー\n");}

/*array MM*/
#include <stdlib.h>


/*
  配列を固定サイズ割り当てするメモリマネージャ
  最大要素数は32個。最大フラグメントサイズは64k
*/

typedef struct NyLPC_TArrayMM NyLPC_TArrayMM_t;

//
struct NyLPC_TArrayMM
{
  NyLPC_TUInt32 _used_bits;
  NyLPC_TInt16 _len;
  NyLPC_TInt16 _size;
};


//管理配列の定義マクロ
#define NyLPC_TArrayMM_def(type_of_item,len_of_item) \
  {                    \
    struct NyLPC_TArrayMM _header;    \
    type_of_item _item[len_of_item];  \
  }

//管理配列の初期化関数
void NyLPC_TArrayMM_initialize(struct NyLPC_TArrayMM* i_item,int i_len_of_array,int i_size_of_item)
{
  //最大32個
  NyLPC_ASSERT(i_len_of_array<=32);

  //管理ヘッダの初期化
  i_item->_used_bits=0;
  i_item->_len=(NyLPC_TInt16)i_len_of_array;
  i_item->_size=(NyLPC_TInt16)i_size_of_item;
}

//アロケータ。しくじるとnull
void* NyLPC_TArrayMM_alloc(struct NyLPC_TArrayMM* i_inst)
{
  NyLPC_TUInt32 b=0x00000001;
  int c;
  for(c=i_inst->_len-1;c>=0;c--)
  {
    if((i_inst->_used_bits&b)==0){
      //アイテター
      i_inst->_used_bits|=b;
      return (((char*)(i_inst+1))+i_inst->_size*c);
    }
    b=b<<1;
  }
  return NULL;
}

//解放
void NyLPC_TArrayMM_free(struct NyLPC_TArrayMM* i_inst,void* i_item)
{
  NyLPC_TUInt32 b=0x00000001;
  int c;
  for(c=i_inst->_len-1;c>=0;c--)
  {
    //オナジノドコー
    if((((char*)(i_inst+1))+i_inst->_size*c)==i_item){
      if((i_inst->_used_bits&b)==b){
        i_inst->_used_bits&=(~b);
        return;//アッター
      }
    }
    b=b<<1;
  }
  //ない
  NyLPC_ABORT();
  return;
}

/*  テスト
*/


struct data{
  int a;
  short b;
  char c;
};

#define MAX_ITEM 32
#define ITEM_TYPE struct data


struct MyClass
{
  struct MMtag NyLPC_TArrayMM_def(ITEM_TYPE,MAX_ITEM) item;
};

struct MyClass my_class;


void main()
{
  struct data* p;
  struct data* a[32];
  int i;
  //領域初期化(宣言文と数値を合せる事!)
  NyLPC_TArrayMM_initialize((NyLPC_TArrayMM_t*)(&my_class.item),MAX_ITEM,sizeof(ITEM_TYPE));
  for(i=0;i<33;i++){
    //アロケートチェック
    p=NyLPC_TArrayMM_alloc((NyLPC_TArrayMM_t*)(&my_class.item));
    if(p==NULL){
      continue;
    }
    a[i]=p;
    (*a[i]).a=192;
    (*a[i]).b=15555;
    (*a[i]).c=23;
  }
  for(i=0;i<11;i++){
    //解放チェック
    NyLPC_TArrayMM_free((NyLPC_TArrayMM_t*)(&my_class.item),a[i]);
    NyLPC_TArrayMM_free((NyLPC_TArrayMM_t*)(&my_class.item),a[i]);
  }
  for(i=0;i<12;i++){
    //再アロケートチェック
    p=NyLPC_TArrayMM_alloc((NyLPC_TArrayMM_t*)(&my_class.item));
    if(p==NULL){
      continue;
    }
    a[i]=p;
    (*a[i]).a=233333;
    (*a[i]).b=15;
    (*a[i]).c=55;
  }
  printf("%d\n",sizeof(NyLPC_TArrayMM_t));
  return;
}