Some old allocator code I want t share (2/2)
From
Branimir Maksimovic @21:1/5 to
All on Mon Oct 11 10:46:46 2021
[continued from previous message]
*pbuf= fnd->second->AcquireBuffer(ppnode);
return fnd->first;
#endif
}
size_t
MemManager::AcquireBuffer(size_t sz,void **pbuf)
{
#ifdef DEBUG_BUFFER_STACK
printf("MemManager::AcquireBuffer(int sz= %d,void **pbuf)\n",sz);
#endif
#ifdef USE_NEW_INTERNAL_STATE
#if 0
printf("MemManager::AcquireBuffer(size= %u,tid= %u): start\n",
sz,pthread_self());
#endif
assert(sz<=~0ul-sizeof(size_t));
sz+=sizeof(size_t);
SpecAllocator *tmp= 0;
if(sz > maxsize()) {
#if !defined(MALLOCATOR)
*pbuf= malloc(sz);
#else
*pbuf= Mallocator::alloc(sz);
#endif
if(!*pbuf) throw std::bad_alloc();
*(size_t*)*pbuf=sz;
*pbuf = (size_t*)*pbuf+1;
return sz;
}
SpecAllocator *allocator= findSpecAllocator(sz);
size_t freemem= 0;
*pbuf= allocator->AcquireBuffer(&tmp,&freemem);
*(size_t*)*pbuf = sz;
*pbuf = (size_t*)*pbuf+1;
if(multi())
{
freememory_+= freemem;
freememory_-= allocator->ChunkSize();
if(freememory_>maxfreememory_)
{
#if 0
printf("MemManager::AcquireMemory[%u,%u](): free %u vs max %u\n",
++mrcnt_,pthread_self(),freememory_,maxfreememory_);
#endif
freememory_-=ReleaseMemory(freememory_ - maxfreememory_);
}
}
//printf("MemManager::AcquireBuffer(size= %u): end\n",sz);
return allocator->ChunkSize();
#else
SpecAllocator *tmp= 0;
container_t::iterator fnd=
lower_bound(cont_.begin(),cont_.end(),std::make_pair(sz,tmp),cmp);
if(fnd == cont_.end()) {
#if !defined(MALLOCATOR)
*pbuf= malloc(sz);
#else
*pbuf= Mallocator::alloc(sz);
#endif
if(!*pbuf) throw std::bad_alloc();
return sz;
}
*pbuf= fnd->second->AcquireBuffer(&tmp);
return fnd->first;
#endif
}
size_t
MemManager::ReallocateBuffer(size_t sz, void **pbuf)
{
if(!*pbuf)return AcquireBuffer(sz, pbuf);
if(!sz)
{
ReleaseBuffer(*pbuf, sz);
return 0;
}
assert(sz<=~0ul-sizeof(size_t));
sz+=sizeof(size_t);
*pbuf = (size_t*)*pbuf-1;
size_t oldsz = *(size_t*)*pbuf;
if(oldsz>=sz)
{
*pbuf = (size_t*)*pbuf+1;
return oldsz;
}
if(oldsz>maxsize())
{
#if !defined(MALLOCATOR)
void* tmpbuf = realloc(*pbuf,sz);
#else
void* tmpbuf = Mallocator::realloc(*pbuf,oldsz,sz);
#endif
if(!tmpbuf)
{
*pbuf = (size_t*)*pbuf+1;
return 0;
}
*pbuf = tmpbuf;
*(size_t*)*pbuf = sz;
*pbuf = (size_t*)*pbuf+1;
return sz;
}
SpecAllocator *oldallocator = findSpecAllocator(oldsz);
if(sz>maxsize())
{
#if !defined(MALLOCATOR)
void* tmpbuf = malloc(sz);
#else
void* tmpbuf = Mallocator::alloc(sz);
#endif
if(!tmpbuf)
{
*pbuf = (size_t*)*pbuf+1;
return 0;
}
memcpy(tmpbuf, *pbuf, oldsz);
size_t freed = oldallocator->ReleaseBuffer(*pbuf);
*pbuf = tmpbuf;
*(size_t*)*pbuf = sz;
*pbuf = (size_t*)*pbuf+1;
if(multi())
{
freememory_+=freed;
if(freememory_>maxfreememory_)
{
#if 0
printf("MemManager::AcquireMemory[%u](%u): free %u vs max %u\n",
++mrcnt_,pthread_self(), freememory_,maxfreememory_); #endif
freememory_-=ReleaseMemory(freememory_ - maxfreememory_);
}
}
return sz;
}
SpecAllocator *newallocator = findSpecAllocator(sz), *atmp=0;
if(newallocator == oldallocator)
{
*(size_t*)*pbuf=sz;
*pbuf = (size_t*)*pbuf+1;
return newallocator->ChunkSize();
}
size_t freemem= 0;
void *tmpbuf= newallocator->AcquireBuffer(&atmp,&freemem);
if(multi())
{
freememory_+= freemem;
freememory_-= newallocator->ChunkSize();
if(freememory_>maxfreememory_)
{
#if 0
printf("MemManager::AcquireMemory[%u,%u](): free %u vs max %u\n",
++mrcnt_,pthread_self(),freememory_,maxfreememory_);
#endif
freememory_-=ReleaseMemory(freememory_ - maxfreememory_);
}
}
memcpy(tmpbuf, *pbuf, oldsz);
size_t freed = oldallocator->ReleaseBuffer(*pbuf);
if(multi())
{
freememory_+=freed;
if(freememory_>maxfreememory_)
{
#if 0
printf("MemManager::AcquireMemory[%u](%u): free %u vs max %u\n",
++mrcnt_,pthread_self(), freememory_,maxfreememory_);
#endif
freememory_-=ReleaseMemory(freememory_ - maxfreememory_);
}
}
*pbuf = tmpbuf;
*(size_t*)*pbuf = sz;
*pbuf = (size_t*)*pbuf + 1;
return newallocator->ChunkSize();
}
size_t
MemManager::MaxSize()
{
#if 1
return UINT_MAX;
#else
container_t::iterator it= cont_.end();
--it;
return it->first;
#endif
}
void
MemManager::ReleaseBuffer(void* buf, SpecAllocator* alloc)
{
size_t freed = alloc->ReleaseBuffer(buf);
if(multi())
{
freememory_+=freed;
if(freememory_>maxfreememory_)
{
#if 0
printf("MemManager::AcquireMemory[%u](%u): free %u vs max %u\n",
++mrcnt_,pthread_self(), freememory_,maxfreememory_); #endif
freememory_-=ReleaseMemory(freememory_ - maxfreememory_);
}
}
}
void
MemManager::ReleaseBuffer(void *buf,size_t sz)
{
if(!buf)return;
#ifdef DEBUG_BUFFER_STACK
printf("MemManager::ReleaseBuffer(char *buf,int sz= %u)\n",sz);
#endif
#ifdef USE_NEW_INTERNAL_STATE
buf = (size_t*)buf-1;
sz = *(size_t*)buf;
if(sz > maxsize()) {
#if !defined(MALLOCATOR)
free(buf);
#else
Mallocator::free(buf,sz);
#endif
return;
}
SpecAllocator *allocator= findSpecAllocator(sz);
size_t freed = allocator->ReleaseBuffer(buf);
if(multi())
{
freememory_+=freed;
if(freememory_>maxfreememory_)
{
#if 0
printf("MemManager::ReleaseBuffer[%d](%u): free %d vs max %d\n",
++mrcnt_,pthread_self(), freememory_,maxfreememory_);
#endif
freememory_-=ReleaseMemory(freememory_ - maxfreememory_);
}
}
#else
SpecAllocator *tmp= 0;
container_t::iterator fnd=
lower_bound(cont_.begin(),cont_.end(),std::make_pair(sz,tmp),cmp);
if(fnd == cont_.end()) {
free(buf);
return;
}
fnd->second->ReleaseBuffer(buf);
#endif
}
bool
MemManager::LostFound(size_t sz,void *first,size_t nodesz)
{
#ifdef USE_NEW_INTERNAL_STATE
SpecAllocator *allocator= 0;
seginfo_t::iterator itr=
lower_bound(seginfos_.begin(),seginfos_.end(),SegInfo(0,sz,0),SegInfo::cmp);
assert(itr!=seginfos_.end());
SegInfo &seginfo= *itr;
size_t allindex= (sz<seginfo.segbase_)?0:(sz-seginfo.segbase_)/seginfo.chunkdiff_;
allocator= seginfo.v_[allindex];
assert(sz == allocator->ChunkSize());
return allocator->LostFound(first,nodesz);
#else
SpecAllocator *tmp= 0;
container_t::iterator fnd=
lower_bound(cont_.begin(),cont_.end(),std::make_pair(sz,tmp),cmp);
if(fnd == cont_.end()) return false;
return fnd->second->LostFound(first);
#endif
}
#ifndef USE_NEW_INTERNAL_STATE
void
MemManager::InstallNode(size_t ibufsz,size_t inodesz)
{
#ifdef DEBUG_BUFFER_STACK
printf("MemManager::InstallNode(size_t bufsz= %u,size_t nodesz= %u): ",
bufsz,nodesz);
#endif
// check if we have node already installed
container_t::iterator itr= cont_.begin();
for(;itr!=cont_.end();++itr)
if(itr->first == bufsz) break;
if(itr != cont_.end()) {
return;
}
#if !defined(MALLOCATOR)
void *node= malloc(sizeof(SpecAllocator));
#else
void *node= Mallocator::alloc(sizeof(SpecAllocator));
#endif
if(node) {
new(node)SpecAllocator(ibufsz,inodesz,multi_);
cont_.push_back(std::make_pair(ibufsz,static_cast<SpecAllocator*>(node)));
}
else throw std::bad_alloc();
std::sort(cont_.begin(),cont_.end(),cmp);
}
#endif
#pragma weak configureMemManager
#ifdef MM_ASSUME_PTHREAD_INITIALIZATION
MemManager::PthreadInitializer MemManager::pthread_initializer_;
void
MemManager::lib_pthread_init_finished()
{
// save initialization manager
// MemManagerTable::instance().Insert(pthread_self(),init_manager());
// create mem_key
pthread_once(&mem_key_once(),&mem_key_alloc);
// init specific
// pthread_setspecific(mem_key(),init_manager());
#ifdef MALLOCATOR
Mallocator::set_lock(true);
#endif
lib_pthread_initialized()= true;
}
#endif
MemManager &
MemManager::instance()
{
//printf("MemManager::instance(): start\n");
setupThreadModel();
//printf("MemManager::instance(): thread model set\n");
if(!multi()) {
if(!manager_) {
#if !defined(MALLOCATOR)
void *tmp= malloc(sizeof(MemManager));
#else
void *tmp= Mallocator::alloc(sizeof(MemManager));
#endif
if(tmp) {
new(tmp)MemManager(pthread_self());
manager_= static_cast<MemManager*>(tmp);
manager_->InstallNodes(multi());
}
else throw std::bad_alloc();
atexit(&destroy);
}
return *manager_;
}
else {
if(false && !lib_pthread_initialized()) {
#if 0
if(!init_manager()) {
// create memmgr
#if !defined(MALLOCATOR)
void *mgr= malloc(sizeof(MemManager));
#else
void *mgr= Mallocator::alloc(sizeof(MemManager));
#endif
if(mgr)
{
new(mgr)MemManager(pthread_self());
}
else throw std::bad_alloc();
#if 0
printf("Manager created: %p, %u (%u)\n",
mgr,pthread_self(),sizeof(MemManager));
#endif
init_manager()= static_cast<MemManager*>(mgr);
#if 1
if(configureMemManager)
configureMemManager(init_manager());
else
#endif
init_manager()->InstallNodes(multi());
}
return *init_manager();
#endif
}
else {
#ifndef MM_ASSUME_PTHREAD_INITIALIZATION
// create mem_key
pthread_once(&mem_key_once(),&mem_key_alloc);
#endif
if(!pthread_getspecific(mem_key())) {
MemManager *mm=
MemManagerTable::instance().FindManager(pthread_self());
if(mm) return *mm;
#if !defined(MALLOCATOR)
void *mgr= malloc(sizeof(MemManager));
#else
void *mgr= Mallocator::alloc(sizeof(MemManager));
#endif
if(mgr)
{
new(mgr)MemManager(pthread_self());
}
else throw std::bad_alloc();
#if 0
printf("Manager created: %p, %u (%u)\n",
mgr,pthread_self(),sizeof(MemManager));
#endif
MemManager *m=static_cast<MemManager*>(mgr);
#if 1
if(configureMemManager)
configureMemManager(m);
else
#endif
m->InstallNodes(multi());
//printf("MemManager::instance(): before inserting to table\n");
MemManagerTable::instance().Insert(pthread_self(),m);
//printf("MemManager::instance(): after table insertion\n");
pthread_setspecific(mem_key(),mgr);
//printf("MemManager::instance(): after specific set\n");
}
return *static_cast<MemManager*>(pthread_getspecific(mem_key()));
}
}
}
void
MemManager::setupThreadModel()
{
//printf("MemManager::setupThreadModel()\n");
pthread_once(&thread_model_once(),&setup_thread_model);
}
void
MemManager::setThreadModel(bool multithread)
{
static bool called= false;
assert(!called);
multi()= multithread;
called= true;
}
void
MemManager::destroy()
{
if(!multi()) {
manager_->~MemManager();
#if !defined(MALLOCATOR)
free(manager_);
#else
Mallocator::free(manager_,sizeof(MemManager));
#endif
}
else {
//printf("MemManager::destroy()\n");
pthread_key_delete(mem_key());
mem_key_once() = (pthread_once_t)PTHREAD_ONCE_INIT;
}
}
void
MemManager::destroy(void *buf)
{
#if 0
printf("MemManager::destroy(void *,tid= %u): should destroy %u manager\n",
pthread_self(),static_cast<MemManager*>(buf)->mytid_);
#endif
#if 1
MemManagerTable::instance().Erase(static_cast<MemManager*>(buf)->mytid_); #else
MemManagerTable::instance().Erase(pthread_self());
#endif
//printf("MemManager::destroy(): manager erased from the global table\n");
static_cast<MemManager*>(buf)->~MemManager();
//printf("MemManager::destroy(): manager destroyed\n");
#if !defined(MALLOCATOR)
free(buf);
#else
Mallocator::free(buf,sizeof(MemManager));
#endif
#if 1
//printf("MemManager::destroy(void *buf): END\n");
#endif
}
void
MemManager::mem_key_alloc()
{
pthread_key_create(&mem_key(),&destroy);
atexit(&destroy);
}
MemManagerTable *MemManagerTable::instance_= 0;
//pthread_once_t MemManagerTable::init_once_= PTHREAD_ONCE_INIT;
MemManagerTable &
MemManagerTable::instance()
{
//printf("MemManagerTable::instance(): before pthread_once\n");
pthread_once(&init_once(),&initialize);
//printf("MemManagerTable::instance(): after pthread_once\n");
return *instance_;
}
MemManager *
MemManagerTable::FindManager(pthread_t tid)
{
//printf("MemManagerTable::FindManager(tid= %d): before lock\n",tid);
AutoLock guard(lock_);
//printf("MemManagerTable::FindManager(tid= %d): locked\n",tid);
map_t::iterator itr= table_.find(tid);
if(itr != table_.end()) return itr->second;
else return 0;
}
bool
MemManagerTable::LostFound(pthread_t tid,size_t bufsz,void *n,size_t nodesz)
{
AutoLock guard(lock_);
map_t::iterator itr= table_.find(tid);
if(itr != table_.end()) return itr->second->LostFound(bufsz,n,nodesz);
else return false;
}
void
MemManagerTable::Insert(pthread_t tid,MemManager *mgr)
{
AutoLock guard(lock_);
table_[tid]= mgr;
}
void
MemManagerTable::Erase(pthread_t tid)
{
AutoLock guard(lock_);
//fprintf(stderr,"MemManagerTable::Erase(pthread_t tid= %u)\n",tid);
map_t::iterator itr= table_.find(tid);
if(itr != table_.end()) table_.erase(itr);
}
void
MemManagerTable::initialize()
{
#if !defined(MALLOCATOR)
void *tmp= malloc(sizeof(MemManagerTable));
#else
void *tmp= Mallocator::alloc(sizeof(MemManagerTable));
#endif
if(tmp) {
//printf("Manager Table created: %p (%u)\n",tmp,sizeof(MemManagerTable));
new(tmp)MemManagerTable();
//printf("Manager Table constructed: %p (%u)\n",tmp,sizeof(MemManagerTable));
instance_= static_cast<MemManagerTable *>(tmp);
atexit(&destroy);
}
else throw std::bad_alloc();
}
void
MemManagerTable::destroy()
{
instance_->~MemManagerTable();
#if !defined(MALLOCATOR)
free(instance_);
#else
Mallocator::free(instance_,sizeof(MemManagerTable));
#endif
instance_= 0;
init_once() = (pthread_once_t)PTHREAD_ONCE_INIT;
}
void* MemManagerPrim::operator new(size_t s)throw (std::bad_alloc)
{
//printf("new: %u\n",s);
void *buf = 0;
MemManager::instance().AcquireBuffer(s,&buf);
return buf;
}
void MemManagerPrim::operator delete(void* p)throw ()
{
//printf("delete: \n");
MemManager::instance().ReleaseBuffer(p, (size_t)0);
//printf("-----------------------------\nend of delete\n\n");
}
void* MemManagerPrim::malloc(size_t s)
try
{
if(MemManager::lib_pthread_initialized()) {
//printf("malloc\n");
void* buf = 0;
MemManager::instance().AcquireBuffer(s, &buf);
return buf;
}
else {
//avoid MemManager interface; use base layer...
s+= sizeof(size_t);
void *buf= Mallocator::alloc(s);
if(!buf) return 0;
*(size_t *)buf= s;
buf= (size_t *)buf + 1;
return buf;
}
}
catch(const std::exception& e)
{
//fprintf(stderr,"memory exception: %s\n", e.what());
return 0;
}
catch(...)
{
//fprintf(stderr,"unkown memory exception\n");
return 0;
}
void* MemManagerPrim::calloc(size_t n, size_t s)
try
{
if(MemManager::lib_pthread_initialized()) {
//printf("calloc: %u of size %u\n",n,s);
void* buf = 0;
MemManager::instance().AcquireBuffer(n*s, &buf);
memset(buf,0,n*s);
return buf;
}
else {
size_t x= n*s;
x+= sizeof(size_t);
void *buf= Mallocator::alloc(x);
if(!buf) return 0;
memset(buf,0,x);
*(size_t *)buf= x;
buf= (size_t *)buf + 1;
return buf;
}
}
catch(const std::exception& e)
{
//fprintf(stderr,"memory exception: %s\n", e.what());
return 0;
}
catch(...)
{
//fprintf(stderr,"unkown memory exception\n");
return 0;
}
void* MemManagerPrim::realloc(void* p, size_t s)
try
{
if(MemManager::lib_pthread_initialized()) {
size_t rc = MemManager::instance().ReallocateBuffer(s, &p);
if(rc)return p;
else return 0;
}
else {
return p;
}
}
catch(const std::exception& e)
{
//fprintf(stderr,"memory exception: %s\n", e.what());
return 0;
}
catch(...)
{
//fprintf(stderr,"unkown memory exception\n");
return 0;
}
void MemManagerPrim::free(void* p)
{
//printf("free: \n");
if(!p)return;
if(MemManager::lib_pthread_initialized()) {
MemManager::instance().ReleaseBuffer(p, (size_t)0);
}
else {
p= (size_t *)p - 1;
size_t s= *(size_t *)p;
Mallocator::free(p,s);
}
}
//============================================================================= // History:
//
// $Log$
// Revision 1.50 2009/07/17 16:16:34 luska
// library repackaged
//
// Revision 1.49 2008/08/05 14:17:33 virtus
// *** empty log message ***
//
// Revision 1.48 2006/01/19 17:08:14 virtus
// ported to openbsd
//
// Revision 1.47 2005/08/18 17:54:34 luska
// ASSUME_PTHREAD_INITIALIZATION switch added
//
// Revision 1.46 2005/08/01 22:41:31 luska
// hm, while initializing pthread use Mallocator interface
//
// Revision 1.45 2005/08/01 20:43:22 luska
// only lock memory banks if pthread init is finished
//
// Revision 1.44 2005/08/01 18:39:48 luska
// *** empty log message ***
//
// Revision 1.43 2005/08/01 18:19:30 luska
// all statics wrapped
//
// Revision 1.42 2005/07/05 18:49:38 build
// resolved namespace and const map key issue
//
// Revision 1.41 2005/01/12 12:59:14 luska
// nasty little fixed
//
// Revision 1.40 2004/10/29 16:41:42 bmaxa
// *** empty log message ***
//
// Revision 1.39 2004/10/29 16:38:53 bmaxa
// *** empty log message ***
//
// Revision 1.38 2004/10/29 16:34:21 bmaxa
// line 202 cast corrected
//
// Revision 1.37 2004/10/28 16:58:37 luska
// f'in printf removed thanks to web team
//
// Revision 1.36 2004/10/26 18:40:13 luska
// *** empty log message ***
//
// Revision 1.35 2004/10/25 21:49:21 bmaxa
// release buffer check for null in mem manager
//
// Revision 1.34 2004/10/25 20:08:54 luska
// *** empty log message ***
//
// Revision 1.33 2004/10/25 20:07:34 luska
// recursion bug at pthread_setspecific fixed
//
// Revision 1.32 2004/10/25 18:15:10 bmaxa
// new,delete
//
// Revision 1.31 2004/10/25 16:56:34 bmaxa
// added malloc....
//
// Revision 1.30 2004/10/21 21:20:49 bmaxa
// *** empty log message ***
//
// Revision 1.29 2004/10/19 20:10:00 bmaxa
// corrected findSpecAllocator
//
// Revision 1.28 2004/10/19 20:01:00 bmaxa
// ReallocBuffer and findSpecAllocator added
//
// Revision 1.27 2004/10/16 00:17:10 bmaxa
// final with tree
//
// Revision 1.26 2004/10/15 21:58:43 luska
// *** empty log message ***
//
// Revision 1.25 2004/10/07 16:50:07 virtus
// *** empty log message ***
//
// Revision 1.24 2004/10/04 19:34:09 bmaxa
// suited for mallocator
//
// Revision 1.23 2004/09/28 19:21:15 bmaxa
// foreigners are up front...
//
// Revision 1.22 2004/09/27 21:09:49 bmaxa
// foreigners are back :)
//
// Revision 1.21 2004/09/27 16:52:42 bmaxa
// ammount of returned memory properly returned and check for null in malloc call for single threaded version
//
// Revision 1.20 2004/09/21 18:53:09 bmaxa
// size_t instead of int
//
// Revision 1.19 2004/09/20 17:26:23 bmaxa
// *** empty log message ***
//
// Revision 1.18 2004/09/20 17:16:01 bmaxa
// size*16 max memory
//
// Revision 1.17 2004/09/20 16:11:43 bmaxa
// list,map into vector
//
// Revision 1.15 2004/09/17 18:25:21 bmaxa
// final
//
// Revision 1.14 2004/09/17 17:42:08 luska
// InstallNodes algorithm changed
//
// Revision 1.13 2004/09/17 17:30:09 bmaxa
// *** empty log message ***
//
// Revision 1.12 2004/09/17 15:13:53 vmp
// mt preallocate 32 units
//
// Revision 1.11 2004/09/16 20:38:35 luska
// *** empty log message ***
//
// Revision 1.10 2004/09/16 20:05:56 bmaxa
// *** empty log message ***
//
// Revision 1.9 2004/09/16 19:36:05 luska
// releasing memory bug fixed
//
// Revision 1.8 2004/09/16 18:36:48 luska
// allocator interface changed due to memory accounting
//
// Revision 1.7 2004/09/16 16:42:10 bmaxa
// corrections...
//
// Revision 1.6 2004/09/15 17:49:47 vmp
// yet another once set for gen allocator
//
// Revision 1.5 2004/09/15 16:26:52 luska
// use of pragma weak again
//
// Revision 1.4 2004/09/15 15:37:22 vmp
// pthread_once_t reseted after destruction
//
// Revision 1.3 2004/09/13 16:54:02 luska
// *** empty log message ***
//
// Revision 1.2 2004/09/13 16:25:00 luska
// new internal state defined
//
// Revision 1.1 2004/09/09 21:11:27 luska
// first implementation
//
//
//
//
// //=============================================================================
--
7-77-777
Evil Sinner!
with software, you repeat same experiment, expecting different results...
--- SoupGate-Win32 v1.05
* Origin: fsxNet Usenet Gateway (21:1/5)