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

基本思想:

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需要多少个块存储。




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值