diff options
Diffstat (limited to 'moses/src/mempool.cpp')
-rw-r--r-- | moses/src/mempool.cpp | 491 |
1 files changed, 491 insertions, 0 deletions
diff --git a/moses/src/mempool.cpp b/moses/src/mempool.cpp new file mode 100644 index 000000000..b56e625a2 --- /dev/null +++ b/moses/src/mempool.cpp @@ -0,0 +1,491 @@ +/****************************************************************************** + IrstLM: IRST Language Model Toolkit + Copyright (C) 2006 Marcello Federico, ITC-irst Trento, Italy + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + 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 GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +******************************************************************************/ + +// An efficient memory pool manager +// by M. Federico +// Copyright Marcello Federico, ITC-irst, 1998 + +#include <iostream> +#include <cassert> +#include "mempool.h" +#include "TypeDef.h" +#include "Util.h" + +using namespace std; + +/*! The pool contains: + - entries of size is + - tables for bs entries +*/ + +mempool::mempool(int is, int bs){ + + // item size must be multiple of memory alignment step (4 bytes) + // example: is is=9 becomes i=12 (9 + 4 - 9 %4 ) + + is=(is>(int)sizeof(char *)?is:0); + + is=is + sizeof(char *) - (is % sizeof(char *)); + + item_size = is; + + block_size = bs; + + true_size = is * bs; + + block_list = new memnode; + + block_list->block = new char[true_size]; + + memset(block_list->block,'0',true_size); + + block_list->next = 0; + + blocknum = 1; + + entries = 0; + + // build free list + + char *ptr = free_list = block_list->block; + + for (int i=0;i<block_size-1;i++) { + *(char **)ptr= ptr + item_size; + ptr+=item_size; + } + *(char **)ptr = NULL; //last item + +} + + +char * mempool::allocate(){ + + char *ptr; + + if (free_list==NULL) + { + memnode *new_block = new memnode; + + new_block->block = new char[true_size]; + + //memset(new_block->block,'0',true_size); + + new_block->next = block_list; + + block_list=new_block; // update block list + + /* update free list */ + + ptr = free_list = block_list->block; + + for (int i=0;i<block_size-1;i++) { + *(char **)ptr = ptr + item_size; + ptr = ptr + item_size; + } + + *(char **)ptr=NULL; + + blocknum++; + } + + assert(free_list); + + ptr = free_list; + + free_list=*(char **)ptr; + + *(char **)ptr=NULL; // reset the released item + + entries++; + + return ptr; + +} + + +int mempool::free(char* addr){ + + // do not check if it belongs to this pool !! + /* + memnode *list=block_list; + while ((list != NULL) && + ((addr < list->block) || + (addr >= (list->block + true_size)))) + list=list->next; + + if ((list==NULL) || (((addr - list->block) % item_size)!=0)) + { + //TRACE_ERR( "mempool::free-> addr does not belong to this pool\n"); + return 0; + } + */ + + *(char **)addr=free_list; + free_list=addr; + + entries--; + + return 1; +} + + +mempool::~mempool() +{ + memnode *ptr; + + while (block_list !=NULL){ + ptr=block_list->next; + delete [] block_list->block; + delete block_list; + block_list=ptr; + } + +} + +void mempool::map (ostream& co){ + + co << "mempool memory map:\n"; + //percorri piu` volte la lista libera + + memnode *bl=block_list; + char *fl=free_list; + + char* img=new char[block_size+1]; + img[block_size]='\0'; + + while (bl !=NULL){ + + memset(img,'#',block_size); + + fl=free_list; + while (fl != NULL){ + if ((fl >= bl->block) + && + (fl < bl->block + true_size)) + { + img[(fl-bl->block)/item_size]='-'; + } + + fl=*(char **)fl; + } + + co << img << "\n"; + bl=bl->next; + } + delete [] img; +} + +void mempool::stat(){ + + TRACE_ERR( "mempool class statistics\n" + << "entries " << entries + << " blocks " << blocknum + << " used memory " << (blocknum * true_size)/1024 << " Kb\n"); +} + + + +strstack::strstack(int bs){ + + size=bs; + list=new memnode; + + list->block=new char[size]; + + list->next=0; + + memset(list->block,'\0',size); + idx=0; + + waste=0; + memory=size; + entries=0; + blocknum=1; + +} + + +void strstack::stat(){ + + TRACE_ERR( "strstack class statistics\n" + << "entries " << entries + << " blocks " << blocknum + << " used memory " << memory/1024 << " Kb\n"); +} + + +char *strstack::push(char *s){ + int len=strlen(s); + + if ((len+1) >= size){ + TRACE_ERR( "strstack::push string is too long\n"); + exit(1); + }; + + if ((idx+len+1) >= size){ + //append a new block + //there must be space to + //put the index after + //the word + + waste+=size-idx; + blocknum++; + memory+=size; + + memnode* nd=new memnode; + nd->block=new char[size]; + nd->next=list; + + list=nd; + + memset(list->block,'\0',size); + + idx=0; + + } + + // append in current block + + strcpy(&list->block[idx],s); + + idx+=len+1; + + entries++; + + return &list->block[idx-len-1]; + +} + + +char *strstack::pop(){ + + if (list==0) return 0; + + if (idx==0){ + + // free this block and go to next + + memnode *ptr=list->next; + + delete [] list->block; + delete list; + + list=ptr; + + if (list==0) + return 0; + else + idx=size-1; + } + + //go back to first non \0 + while (idx>0) + if (list->block[idx--]!='\0') + break; + + //go back to first \0 + while (idx>0) + if (list->block[idx--]=='\0') + break; + + entries--; + + if (list->block[idx+1]=='\0') + { + idx+=2; + memset(&list->block[idx],'\0',size-idx); + return &list->block[idx]; + } + else{ + idx=0; + memset(&list->block[idx],'\0',size); + return &list->block[0]; + } +} + + +char *strstack::top(){ + + int tidx=idx; + memnode *tlist=list; + + if (tlist==0) return 0; + + if (idx==0){ + + tlist=tlist->next; + + if (tlist==0) return 0; + + tidx=size-1; + } + + //go back to first non \0 + while (tidx>0) + if (tlist->block[tidx--]!='\0') + break; + + //aaa\0bbb\0\0\0\0 + + //go back to first \0 + while (tidx>0) + if (tlist->block[tidx--]=='\0') + break; + + if (tlist->block[tidx+1]=='\0') + { + tidx+=2; + return &tlist->block[tidx]; + } + else{ + tidx=0; + return &tlist->block[0]; + } + +} + + +strstack::~strstack(){ + memnode *ptr; + while (list !=NULL){ + ptr=list->next; + delete [] list->block; + delete list; + list=ptr; + } +} + + +storage::storage(int maxsize,int blocksize) +{ + newmemory=0; + newcalls=0; + setsize=maxsize; + poolsize=blocksize; //in bytes + poolset=new mempool* [setsize+1]; + for (int i=0;i<=setsize;i++) + poolset[i]=NULL; +} + + +storage::~storage(){ + for (int i=0;i<=setsize;i++) + if (poolset[i]) + delete poolset[i]; + delete [] poolset; +} + +char *storage::allocate(int size){ + + if (size<=setsize){ + if (!poolset[size]){ + poolset[size]=new mempool(size,poolsize/size); + } + return poolset[size]->allocate(); + } + else{ + + newmemory+=size+8; + newcalls++; + char* p=(char *)calloc(sizeof(char),size); + if (p==NULL){ + TRACE_ERR( "storage::alloc insufficient memory\n"); + exit(1); + } + return p; + } +} + +char *storage::reallocate(char *oldptr,int oldsize,int newsize){ + + char *newptr; + + assert(newsize>oldsize); + + if (oldsize<=setsize){ + if (newsize<=setsize){ + if (!poolset[newsize]) + poolset[newsize]=new mempool(newsize,poolsize/newsize); + newptr=poolset[newsize]->allocate(); + memset((char*)newptr,0,newsize); + } + else + newptr=(char *)calloc(sizeof(char),newsize); + + if (oldptr && oldsize){ + memcpy(newptr,oldptr,oldsize); + poolset[oldsize]->free(oldptr); + } + } + else{ + newptr=(char *)realloc(oldptr,newsize); + if (newptr==oldptr){ + TRACE_ERR( "r\b"); + } + else{ + TRACE_ERR( "a\b"); + } + } + if (newptr==NULL){ + TRACE_ERR( "storage::realloc insufficient memory\n"); + exit(1); + } + + return newptr; +} + +int storage::free(char *addr,int size){ + + /* + while(size<=setsize){ + if (poolset[size] && poolset[size]->free(addr)) + break; + size++; + } + */ + + if (size>setsize) + return free(addr),1; + else{ + poolset[size] && poolset[size]->free(addr); + } + return 1; +} + +void storage::stat(){ + int used=0; + int memory=sizeof(char *) * setsize; + int waste=0; + + for (int i=0;i<=setsize;i++) + if (poolset[i]){ + used++; + memory+=poolset[i]->used(); + waste+=poolset[i]->wasted(); + } + + TRACE_ERR( "storage class statistics\n" + << "alloc entries " << newcalls + << " used memory " << newmemory/1024 << "Kb\n" + << "mpools " << setsize + << " active " << used + << " used memory " << memory/1024 << "Kb" + << " wasted " << waste/1024 << "Kb\n"); +} |