您的位置:首页 > 其它

小样:内存管理系统实现,提供可持久化功能

2013-11-22 14:24 501 查看
基本思想:
1.把内存分块管理,这里是把内存分为64字节一块
2.下一块的地址,不是存储下一块的地址,而是相对偏移地址,为了持久化,
3.把首64字节为保留空间,分别记录 空闲块链表的首地址,使用块链表的首地址

首64字节定义
struct HeadInfo
{
int freeList;
int usedList;
unsigned int count;
int unused[]
};


块的定义如下

class DString
{
public:
int size;
//the next node offset
int next;
char valueStr[valueSize];
DString()
{
size=0;
next=-1;
memset(valueStr,0,valueSize*sizeof(char));
}
DString(char *str,int length)
{
size=0;
next=-1;
memset(valueStr,0,sizeof(char)*valueSize);
assert(length<=valueSize);
memcpy(valueStr,str,length);
size=length;
}
void setSize(int size)
{
this->size=size;
}
void setNextLocation(int location)
{
next=location;
}
~DString()
{
size=0;
next=0;
memset(valueStr,0,valueSize*sizeof(char));
}
};
记得块的初始化,其中 next 执行该块的下一块相对偏移量,通过基地址+next可以找到下一块。

内存管理的集体实现

#include<iostream>
#include<fstream>
#include "StringPool.h"
#include"dString.h"
#include"HeadInfo.h"
using namespace std;
CStringPool::CStringPool ():poolSize(0x1000)
{
cout<<"CStringPool"<<endl;
assert(sizeof(HeadInfo)<=sizeof(DString));
poolP=NULL;
poolP=(char *)malloc(sizeof(char)*poolSize);
assert(poolP!=NULL);
DString fillInfo;
int DSsize=sizeof(DString);
int offset=0;
int nodeCount=poolSize/sizeof(DString);
for(int i=0;i<nodeCount;i++)
{
if(i!=nodeCount-1)
{
fillInfo.setNextLocation(offset+DSsize);
}
else
{
fillInfo.setNextLocation(-1);
}
memcpy(poolP+offset,&fillInfo,DSsize);
offset+=DSsize;
}

head=(HeadInfo*)poolP;
head->freeList=0+DSsize;
head->count=0;
head->usedList=-1;
#ifdef BUG
printList(head->freeList);
#endif
}

void CStringPool::printList(int index)
{
DString * tem1,*tem2;
int prelocation,nowLocation;
tem1=getNodeList(index);
if(tem1!=NULL)
cout<<"locaiton : "<<index<<endl;
prelocation=index;
while((tem2=getNextNode(tem1))!=NULL)
{
nowLocation=tem1->next;
cout<<"prelocaiton: "<<prelocation<<", now location"<<nowLocation<<" "<<nowLocation-prelocation<<endl;
prelocation=nowLocation;
tem1=tem2;
}
}

DString* CStringPool::getNodeList(int offset)
{
DString *beginLocation;
beginLocation=(DString*) ( poolP+offset);
return beginLocation;
}
int CStringPool ::getNodeIndex(DString *node)
{
int index= (char *)node -(char*)poolP;
if((unsigned int)index>(poolSize-sizeof(DString)))
{
return -1;
}
return index;
}

DString *  CStringPool::getNextNode( DString *nowNode)
{
DString * temP=NULL;
if(nowNode->next>0)
{
temP=(DString*) (poolP+nowNode->next);
}
return temP;
}

DString* CStringPool::getFreeNodesAndRemoveFromeFreelist(int nodeNum)
{
if((head->count+nodeNum)*sizeof(DString)>poolSize)
{
return NULL;
}
DString *beginLocation;
DString * endLocation=NULL;
beginLocation=(DString*)(poolP+head->freeList);
endLocation=beginLocation;
for(int i=1;i<nodeNum;i++)
{
endLocation=getNextNode(endLocation);
assert(endLocation!=NULL);
}
head->freeList=endLocation->next;
endLocation->next=-1;
return beginLocation;
}
DString* CStringPool::getPreNodeInUseList(int index)
{
int usedbegin=head->usedList;
//if index pointer to the head node
if(usedbegin==index)
{
return getNodeList(index);
}
if(usedbegin<0)
{
return NULL;
}
DString *usedList=getNodeList(usedbegin);
while(usedList!=NULL)
{
if(usedList->next==index)
{
return usedList;
}
usedList=getNextNode(usedList);
}
return NULL;
}

/*
return 0 oK
return -1 the index is out of range;
*/
int CStringPool::getUsedNodesAndRemoveFromeUsedlist(int index)
{
DString *preNode=getPreNodeInUseList(index);
if(preNode!=NULL)
{
int * preIndexP;
if(index==head->usedList)
{
preIndexP=&(head->usedList);
}
else
{
preIndexP=&(preNode->next);
}
DString *delNode=getNodeList(index);
int delLength=delNode->size;
assert(delLength>0);
DString *tem=delNode;
int inNodeOff=sizeof(delNode->next)+sizeof(delNode->size);
//clear the node;
while(delLength>0)
{
if((unsigned int)delLength>(sizeof(DString)-inNodeOff))
{
tem->size=-1;
memset(tem->valueStr,0,sizeof(DString)-inNodeOff);
tem=getNextNode(tem);
}
else
{
tem->size=-1;
memset(tem->valueStr,0,sizeof(DString)-inNodeOff);
break;
}
delLength=delLength-sizeof(DString)+inNodeOff;
}
// link the used list
*preIndexP=tem->next;
tem->next=-1;
//link to the free list
int freeListBeginOffset=head->freeList;
head->freeList=getNodeIndex(delNode);
tem->next=freeListBeginOffset;
return 0;
}
else
{
return -1;
}

}
CStringPool::~CStringPool(void)
{
free(poolP);
}

int CStringPool::set(const string &strIn)
{
DString * nodeList;
int index=-1;
//一个节点中,非用了存储数据的长度
int InnodeOff=sizeof(nodeList->size)+sizeof(nodeList->next);
//将要存储的数据需要占几个节点
int nodeNum=(strIn.size()+sizeof(DString)-1)/(sizeof(DString)-InnodeOff);
const char *cStrP=strIn.c_str();
int length=strIn.size();
nodeList=getFreeNodesAndRemoveFromeFreelist(nodeNum);
if(nodeList==NULL)
{
return -2;
}
index=(char *)nodeList-(char *)poolP;
nodeList->size=strIn.size();
//DString* beginLocation;
//DString *tem;
int leftSize= length;
while(leftSize>0)
{
leftSize=leftSize-sizeof(DString)+InnodeOff;
if(leftSize>=0)
{
memcpy(nodeList->valueStr,cStrP,sizeof(DString)-InnodeOff);
cStrP=cStrP+(sizeof(DString)-InnodeOff);
nodeList=getNextNode(nodeList);
}
else
{
memcpy(nodeList->valueStr,cStrP,leftSize+sizeof(DString)-InnodeOff);
nodeList->next=-1;
}
}
// update the used list;
int oldUsedBeginOffset=head->usedList;
head->usedList=index;
nodeList->next=oldUsedBeginOffset;

return index;
}

bool CStringPool::get(int index, string & strOut)
{
//strOut.clear();
DString *strP=getNodeList(index);
if(strP==NULL)
{
cout<<"wrong index"<<endl;
return false;
}
int strLength=strP->size;
int inNodeOff=sizeof(strP->next)+sizeof(strP->size);
#ifdef BUG
cout<<"the length of the string you will get  is "<<strP->size<<endl;
#endif
while(strLength>0)
{
if((unsigned int)strLength>(sizeof(DString)-inNodeOff))
{
strOut.append(strP->valueStr,(sizeof(DString)-inNodeOff));
strP=getNextNode(strP);
}
else
{
strOut.append(strP->valueStr,strLength);
}
strLength=strLength-(sizeof(DString)-inNodeOff);
}
//cout<<strOut<<endl;
return true;
}

bool CStringPool:: del(int index)
{
int state=getUsedNodesAndRemoveFromeUsedlist(index);
if(state==0)
return true;
else
return false;
}

bool CStringPool::saveToFile(const string &filePath)
{
fstream outPut;
outPut.open(filePath.c_str(),ios::binary|ios::out);
if(outPut!=0)
{
cout<<"open file error"<<endl;
return false;
}

//write head to file
char *p ;
int length=poolSize;
p=poolP;
for(int i=0;i<length;i++)
{
outPut.put(*p);
p++;
}
return true;
}

bool CStringPool::loadFromFile(const string &filePath)
{
fstream input;
input.open(filePath.c_str(),ios::binary|ios::in );
if(input==NULL)
{
cout <<"open file error"<<endl;
return false;
}
int length=poolSize;
char * p=poolP;
for(int i=0;i<length;i++)
{
if(input.get(*p))
{
p++;
}

}
return true;
}


这里提供的是字符串的存储,能存储字符串就可以存储所有的类型,对于一个字符串STR如果大小大于64-8个字节,就采用,多个块存储,如 a1,a2。。。an n个块存储,第一个块a1 -> size 为字符串的大小 STR.size(),其他为0;只要找到第一个块,我们就知道这个字符串STR需要多少个块存储。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: