Some old allocator code I want t share

16 views
Skip to first unread message

Branimir Maksimovic

unread,
Oct 11, 2021, 6:46:57 AMOct 11
to
//=============================================================================
//
// Copyright : (c) 2004 by Dzenis Softic / http://www.dzeni.com
//
// Filename :
//
// Description:
//
// Company : Seenetix D.O.O.
//
// Authors :
//
// $Id$
//
//=============================================================================

#ifndef VMP_BUFFERED_MEM_MANAGER_H
#define VMP_BUFFERED_MEM_MANAGER_H

#include <map>
#include <list>
#include <vector>
#include <utility>

#include <stdio.h>

#include <pthread.h>
#include <cstdlib>
#include <new>
#include <stdlib.h>

#include "vmpthreads.h"

/* use new allocator */
#define MALLOCATOR

#if !defined(MALLOCATOR)
#include "vmp_malloc_allocator.h"
#else
#include "vmp_mallocator.h"
#endif

class SpecAllocator
{
public:

SpecAllocator(size_t buffsz,size_t nodesz,bool threadmodel);
~SpecAllocator();

void *AcquireBuffer(SpecAllocator **ppnode,size_t *freemem);
size_t ReleaseBuffer(void *buf);

size_t ChunkSize() {return bufsz_;}

protected:

bool LostFound(void *first,size_t nodesz);
size_t AcquireMemory();
size_t ReleaseMemory(size_t size);

struct bigBufferNode_t
{
bigBufferNode_t *next;
};

bigBufferNode_t *first_;

size_t bufsz_; // mem unit size
size_t nodesz_; // preallocate units

size_t used_; // allocated memory


bool multi_; // thread model

typedef std::pair<size_t,bigBufferNode_t*> mapvalue_t;
typedef std::pair<pthread_t, mapvalue_t> value_t;

#if !defined(MALLOCATOR)
typedef std::vector<value_t, TMallocAllocator<value_t> > map_t;
#else
typedef std::vector<value_t, TMallocator<value_t> > map_t;
#endif

map_t foreigners_;

typedef std::pair<size_t,void *> listvalue_t;

#if !defined(MALLOCATOR)
typedef std::vector<listvalue_t,TMallocAllocator<listvalue_t> > list_t; // memory allocated
#else
typedef std::vector<listvalue_t,TMallocator<listvalue_t> > list_t; // memory allocated
#endif

list_t amem_; // memory allocated
RecursiveMutex lostLock_;

private:

void hlpDestroy();

static size_t &header_size() {

static size_t _header_size= (sizeof(pthread_t) + 3) & ~3;
return _header_size;
}

// static size_t header_size_;

SpecAllocator(const SpecAllocator&);
SpecAllocator& operator=(const SpecAllocator&);

friend class MemManager;
friend class GenAllocator;
};


class GenAllocator
{
public:

static void setThreadModel(bool);

template<int ObjectSize> static GenAllocator &instance() {

setupThreadModel();
if(multi()) {

pthread_once(&mem_key_once(),&mem_key_alloc);
if(!pthread_getspecific(mem_key())) {

#if !defined(MALLOCATOR)
void *tmp= malloc(sizeof(map_t));
#else
void *tmp= Mallocator::alloc(sizeof(map_t));
#endif
new(tmp)map_t();
pthread_setspecific(mem_key(),tmp);
}
map_t &m=
*static_cast<map_t *>(pthread_getspecific(mem_key()));
GenAllocator *a= 0;
map_t::iterator itr= m.find(ObjectSize);
if(itr != m.end()) a= itr->second;
else {

#if !defined(MALLOCATOR)
void *tmp= malloc(sizeof(GenAllocator));
#else
void *tmp= Mallocator::alloc(sizeof(GenAllocator));
#endif
new(tmp)GenAllocator(ObjectSize);
a= static_cast<GenAllocator*>(tmp);
m[ObjectSize]= a;
}
return *a;
}
else {

static GenAllocator *a= 0;
if(!a) {

#if !defined(MALLOCATOR)
void *tmp= malloc(sizeof(GenAllocator));
#else
void *tmp= Mallocator::alloc(sizeof(GenAllocator));
#endif
new(tmp)GenAllocator(ObjectSize);
a= static_cast<GenAllocator*>(tmp);
}
return *a;
}
}

GenAllocator(size_t bufsz);
GenAllocator(size_t ibufsz,size_t nodesz);
~GenAllocator();

void *Alloc(size_t sz);
void Free(void *p,size_t sz);

protected:

static void setupThreadModel();

#if !defined(MALLOCATOR)
typedef std::map<const size_t,GenAllocator*,std::less<const size_t>,TMallocAllocator<std::pair<const size_t,GenAllocator*> > > map_t;
#else
typedef std::map<const size_t,GenAllocator*,std::less<const size_t>,TMallocator<std::pair<const size_t,GenAllocator*> > > map_t;
#endif

size_t bufsz_;
size_t maxfreememory_; // max free memory which can be holded by manager
size_t freememory_; // current free memory holded by manager

SpecAllocator allocator_;

static bool &multi() {

static bool _multi= true;
return _multi;
}
//static bool multi_;

static void destroy();
static void destroy(void *);
static void mem_key_alloc();

// static void set_thread_model(); can't see implementation


static pthread_key_t &mem_key() {

static pthread_key_t _mem_key;
return _mem_key;
}
//static pthread_key_t mem_key_;

static pthread_once_t &mem_key_once() {

static pthread_once_t _mem_key_once= PTHREAD_ONCE_INIT;
return _mem_key_once;
}
//static pthread_once_t mem_key_once_;

/*
static pthread_once_t &thread_model_once() {

static pthread_once_t _thread_model_once= PTHREAD_ONCE_INIT;
return _thread_model_once;
}
*/
// static pthread_once_t thread_model_once_;

private:

GenAllocator &operator=(const GenAllocator &);
GenAllocator(const GenAllocator &);
};


#ifdef DEBUG_BUFFER_STACK

#define REGISTER_ALLOC(ObjectType) \
static void *operator new(size_t sz) { \
printf("%s::new(size_t sz= %d)\n",#ObjectType,sz); \
return GenAllocator::instance<sizeof(ObjectType)>().Alloc(sz); } \
static void *operator new[](size_t sz) { \
printf("%s::new[](size_t sz= %d)(sizeof(%s)= %d)\n", \
#ObjectType,sz,#ObjectType,sizeof(ObjectType)); \
void *tmp; \
MemManager::instance().AcquireBuffer(sz,&tmp); \
return tmp; } \
static void operator delete(void *p,size_t sz) { \
printf("%s::delete(void *ptr,size_t sz= %d)\n",#ObjectType,sz); \
return GenAllocator::instance<sizeof(ObjectType)>().Free(p,sz); } \
static void operator delete[](void *p,size_t sz) { \
printf("%s::delete[](void *,size_t sz= %d)(sizeof(%s)= %d)\n", \
#ObjectType,sz,#ObjectType,sizeof(ObjectType)); \
MemManager::instance().ReleaseBuffer(p,sz); }

#else

#define REGISTER_ALLOC(ObjectType) \
static void *operator new(size_t sz) { \
return GenAllocator::instance<sizeof(ObjectType)>().Alloc(sz); } \
static void *operator new[](size_t sz) { \
void *tmp; \
MemManager::instance().AcquireBuffer(sz,&tmp); \
return tmp; } \
static void operator delete(void *p,size_t sz) { \
return GenAllocator::instance<sizeof(ObjectType)>().Free(p,sz); } \
static void operator delete[](void *p,size_t sz) { \
MemManager::instance().ReleaseBuffer(p,sz); }

#define REGISTER_GEN_ALLOC \
static void *operator new(size_t sz) { \
void *tmp; \
MemManager::instance().AcquireBuffer(sz,&tmp); \
return tmp; } \
static void *operator new[](size_t sz) { \
void *tmp; \
MemManager::instance().AcquireBuffer(sz,&tmp); \
return tmp; } \
static void operator delete(void *p,size_t sz) { \
MemManager::instance().ReleaseBuffer(p,sz); } \
static void operator delete[](void *p,size_t sz) { \
MemManager::instance().ReleaseBuffer(p,sz); }

#endif


#define USE_NEW_INTERNAL_STATE
//#define MM_ASSUME_PTHREAD_INITIALIZATION // mind libpthread initialization

class MemManager
{
public:

static void setThreadModel(bool multi);

static MemManager& instance();

~MemManager();

int AcquireBuffer(size_t sz,void **pbuf,SpecAllocator **pnode);
size_t AcquireBuffer(size_t sz,void **pbuf);
size_t ReallocateBuffer(size_t sz, void **pbuf);
void ReleaseBuffer(void *buf,SpecAllocator*);
void ReleaseBuffer(void *buf,size_t sz);

size_t MaxSize();

static bool &multi()
{
static bool _multi= true;
return _multi;
}

// static bool multi_;

/*
static bool &recursion() {

static bool _recursion= false;
return _recursion;
}
*/

static bool &lib_pthread_initialized() {

#ifdef MM_ASSUME_PTHREAD_INITIALIZATION
/**
in case we need to be aware of libpthread during initialization process
start assuming libpthread is not initialized. While flag isn't set
MemManager interface shouldn't be used. When libpthread is initialized
user may set this flag so that memory management is done through
MemManager interface.
*/
static bool _pthread_initialized= false;
#else
/**
libpthread doesn't use dynamic memory during initialization. We may
start using MemMemory interface from the very begining...
*/
static bool _pthread_initialized= true;
#endif

return _pthread_initialized;
}

protected:

MemManager(pthread_t);

bool LostFound(size_t bufsz,void *first,size_t inodesz);

SpecAllocator* findSpecAllocator(size_t sz);
#ifndef USE_NEW_INTERNAL_STATE
void InstallNode(size_t,size_t);
#endif

size_t ReleaseMemory(size_t sz);
void InstallNodes(bool);

static void setupThreadModel();

#ifndef USE_NEW_INTERNAL_STATE
// definition of the internal state: allocator info container
typedef std::pair<size_t,SpecAllocator *> content_t;

#if !defined(MALLOCATOR)
typedef std::vector<content_t,TMallocAllocator<content_t> > container_t;
#else
typedef std::vector<content_t,TMallocator<content_t> > container_t;
#endif

static bool cmp(const content_t &,const content_t &);

container_t cont_;
#endif

static MemManager *manager_;

//static bool multi_;

static void destroy();
static void destroy(void *);
static void mem_key_alloc();

static pthread_key_t &mem_key()
{
static pthread_key_t _mem_key;
return _mem_key;
}
static pthread_once_t &mem_key_once()
{
static pthread_once_t _mem_key_once= PTHREAD_ONCE_INIT;;
return _mem_key_once;
}

//static pthread_key_t mem_key_;
//static pthread_once_t mem_key_once_;

#ifdef USE_NEW_INTERNAL_STATE
struct SegInfo
{
SegInfo(size_t segbase,size_t segend,size_t cdiff):
segbase_(segbase),segend_(segend),chunkdiff_(cdiff){}
size_t segbase_;
size_t segend_;
size_t chunkdiff_;

#if !defined(MALLOCATOR)
typedef std::vector<SpecAllocator*,TMallocAllocator<SpecAllocator*> > v_t;
#else
typedef std::vector<SpecAllocator*,TMallocator<SpecAllocator*> > v_t;
#endif

v_t v_;
static bool cmp(const SegInfo &lhs,const SegInfo &rhs) {
return lhs.segend_<rhs.segend_;
}
};

#if !defined(MALLOCATOR)
typedef std::vector<SegInfo,TMallocAllocator<SegInfo> > seginfo_t;
#else
typedef std::vector<SegInfo,TMallocator<SegInfo> > seginfo_t;
#endif

seginfo_t seginfos_;

static size_t &maxsize()
{
static size_t _maxsize= 65536-sizeof(size_t);
return _maxsize;
}

static size_t &segmentsize()
{
static size_t _segmentsize= 12;
return _segmentsize;
}

//static size_t maxsize_;
//static size_t segmentsize_;

size_t maxfreememory_; // max free memory which can be holded by manager
size_t freememory_; // current free memory holded by manager

size_t mrcnt_;

pthread_t mytid_;
#endif

/*
static MemManager *&init_manager() {

static MemManager *_init_manager= 0;
return _init_manager;
}
*/

#ifdef MM_ASSUME_PTHREAD_INITIALIZATION
/**
define global static object which will tell us when lib's initialization
is finished. Start using MemManager interface by switching on init flag.
*/
static void lib_pthread_init_finished();

class PthreadInitializer {

public:

PthreadInitializer()
{
if(__malloc_hook && __free_hook)
{
void* p = __malloc_hook(16,0);
__free_hook(p,0);
}
else perror("__malloc__hook || __free_hook NULL!");
MemManager::lib_pthread_init_finished();
}

~PthreadInitializer() {

MemManager::lib_pthread_initialized()= false;
#ifdef MALLOCATOR
Mallocator::set_lock(false);
#endif
}
};
static PthreadInitializer pthread_initializer_;

friend class PthreadInitializer;
#endif

friend class MemManagerTable;
};

struct MemManagerPrim{
void* operator new(size_t s)throw (std::bad_alloc);
inline void* operator new[](size_t s)throw (std::bad_alloc)
{
return MemManagerPrim::operator new(s);
}
void operator delete(void* p)throw ();
inline void operator delete[](void* p)throw ()
{
MemManagerPrim::operator delete(p);
}
static void* malloc(size_t s);
static void* calloc(size_t n, size_t s);
static void* realloc(void* p, size_t s);
static void free(void* p);
};

// application callbacks
extern "C"
{
void setupMemoryThreadModel();
void configureMemManager(MemManager *);
}

#endif

//=============================================================================
// History:
//
// $Log$
// Revision 1.26 2009/07/17 16:16:34 luska
// library repackaged
//
// Revision 1.25 2006/01/19 17:08:14 virtus
// ported to openbsd
//
// Revision 1.24 2005/08/18 17:54:34 luska
// ASSUME_PTHREAD_INITIALIZATION switch added
//
// Revision 1.23 2005/08/04 18:08:24 bmaxa
// *** empty log message ***
//
// Revision 1.22 2005/08/01 22:41:31 luska
// hm, while initializing pthread use Mallocator interface
//
// Revision 1.21 2005/08/01 21:37:32 luska
// reset Mallocator's lock flag in PthreadInitializer's destructor
//
// Revision 1.20 2005/08/01 21:28:37 vmp
// destructor for PthreadInitializer resets lib_pthread_initialized flag
//
// Revision 1.19 2005/08/01 20:43:22 luska
// only lock memory banks if pthread init is finished
//
// Revision 1.18 2005/08/01 18:19:30 luska
// all statics wrapped
//
// Revision 1.17 2005/07/05 18:49:38 build
// resolved namespace and const map key issue
//
// Revision 1.16 2005/01/12 12:59:14 luska
// nasty little fixed
//
// Revision 1.15 2004/10/25 18:15:10 bmaxa
// new,delete
//
// Revision 1.14 2004/10/25 16:56:34 bmaxa
// added malloc....
//
// Revision 1.13 2004/10/19 20:01:00 bmaxa
// ReallocBuffer and findSpecAllocator added
//
// Revision 1.12 2004/10/15 21:58:43 luska
// *** empty log message ***
//
// Revision 1.11 2004/10/05 19:31:20 bmaxa
// typo's
//
// Revision 1.10 2004/10/04 19:34:09 bmaxa
// suited for mallocator
//
// Revision 1.9 2004/09/21 18:53:09 bmaxa
// size_t instead of int
//
// Revision 1.8 2004/09/20 16:11:43 bmaxa
// list,map into vector
//
// Revision 1.7 2004/09/16 19:36:00 luska
// releasing memory bug fixed
//
// Revision 1.6 2004/09/16 18:36:41 luska
// allocator interface changed due to memory accounting
//
// Revision 1.5 2004/09/16 16:42:10 bmaxa
// corrections...
//
// Revision 1.4 2004/09/15 17:55:57 luska
// *** empty log message ***
//
// Revision 1.3 2004/09/15 17:15:19 luska
// REGISTER_GEN_ALLOC
//
// 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
//
//
//
//
//
//=============================================================================

/** and now cpp */
//=============================================================================
//
// Copyright : (c) 2004 by Dzenis Softic / http://www.dzeni.com
//
// Filename :
//
// Description:
//
// Company : Seenetix D.O.O.
//
// Authors :
//
// $Id$
//
//=============================================================================


#include <algorithm>
#include <exception>
#include <limits.h>
#include <cstring>

#include "vmp_buffered_mem_manager.h"
#ifdef USE_NEW_INTERNAL_STATE
#include <math.h>
#endif

#include <assert.h>

#define STORAGE_SIZE 524288

#define MT_PREALLOCATE_UNITS 32
#define ST_PREALLOCATE_UNITS 32


class MemManagerTable
{
public:

static MemManagerTable &instance();

void Insert(pthread_t,MemManager *);
void Erase(pthread_t);

bool LostFound(pthread_t tid,size_t bufsz,void *first,size_t nodesz);
MemManager *FindManager(pthread_t tid);

protected:

#if !defined(MALLOCATOR)
typedef std::map<const pthread_t,MemManager *,std::less<const pthread_t>,TMallocAllocator<std::pair<const pthread_t,MemManager *> > > map_t;
#else
typedef std::map<const pthread_t,MemManager *,std::less<const pthread_t>,TMallocator<std::pair<const pthread_t,MemManager *> > > map_t;
#endif

map_t table_;
RecursiveMutex lock_;

static void initialize();
static void destroy();
static MemManagerTable *instance_;

static pthread_once_t &init_once() {

static pthread_once_t _init_once= (pthread_once_t)PTHREAD_ONCE_INIT;
return _init_once;
}
//static pthread_once_t init_once_;
};


//size_t SpecAllocator::header_size_= (sizeof(pthread_t) + 3) & ~3;


SpecAllocator::SpecAllocator(size_t bufsz,size_t nodesz,bool threadmodel):
first_(0)
,bufsz_(bufsz)
,nodesz_(nodesz)
,used_(0)
,multi_(threadmodel)
{
}


void
SpecAllocator::hlpDestroy()
{
while(first_) {

bigBufferNode_t *tmp= first_->next;
#if !defined(MALLOCATOR)
free((char *)first_ - header_size_);
#else
size_t bufsz = bufsz_;
if(bufsz_ < sizeof(bigBufferNode_t)) bufsz= sizeof(bigBufferNode_t);
Mallocator::free((char *)first_ - header_size(),bufsz + header_size());
#endif
first_= tmp;
}
}


SpecAllocator::~SpecAllocator()
{
if(multi_) {

hlpDestroy();
while(!amem_.empty()) {

first_= static_cast<bigBufferNode_t *>(amem_.back().second);
hlpDestroy();
amem_.pop_back();
}
for(map_t::iterator itr= foreigners_.begin();itr!=foreigners_.end();++itr){

if(!MemManagerTable::instance().LostFound(itr->first,bufsz_,itr->second.second,itr->second.first)) {

first_= itr->second.second;
hlpDestroy();
}
}
}
else {

for(list_t::iterator i= amem_.begin();i != amem_.end();++i) {
#if !defined(MALLOCATOR)
free(i->second);
#else
size_t bufsz = bufsz_;
if(bufsz_ < sizeof(bigBufferNode_t)) bufsz= sizeof(bigBufferNode_t);
Mallocator::free(i->second,bufsz*nodesz_);
#endif
}
}
}


bool
SpecAllocator::LostFound(void *first,size_t nodesz)
{
AutoLock guard(lostLock_);
amem_.push_back(std::make_pair(nodesz,static_cast<bigBufferNode_t *>(first)));
return true;
}


size_t
SpecAllocator::AcquireMemory()
{
if(multi_) {

// use foreigners if any
map_t::reverse_iterator mitr= foreigners_.rbegin();
if(mitr != foreigners_.rend())
{

first_= mitr->second.second;
size_t tmp= mitr->second.first;
foreigners_.pop_back(); // foreigners_.erase(mitr);
// there is no reverse iterator version of erase ?!
return tmp*bufsz_;
}

// use lost if any
{
AutoLock guard(lostLock_);
if(!amem_.empty())
{
first_= static_cast<bigBufferNode_t*>(amem_.back().second);
size_t tmp= amem_.back().first;
amem_.pop_back();
return tmp*bufsz_;
}
}

// have no luck: must malloc
bigBufferNode_t *tmp= (bigBufferNode_t*)&first_;
bool b= false;
size_t bufsz = bufsz_;
if(bufsz_ < sizeof(bigBufferNode_t)) bufsz= sizeof(bigBufferNode_t);
size_t nodesAcquired = 0;
for(size_t i= 0;i<nodesz_;++i,++nodesAcquired)
{

#if !defined(MALLOCATOR)
void *p= malloc(bufsz+header_size());
#else
void* p= Mallocator::alloc(bufsz+header_size());
#endif

if(!p)
{
if(b) break;
else throw std::bad_alloc();
}

*(pthread_t *)p= pthread_self();
p = (char*)p+header_size();

b= true;
tmp->next= static_cast<bigBufferNode_t*>(p);
tmp= tmp->next;
}
tmp->next= 0;

return nodesAcquired*bufsz_;
}
else {

// single thread model
size_t bufsz = bufsz_;
if(bufsz_ < sizeof(bigBufferNode_t)) bufsz= sizeof(bigBufferNode_t);
#if !defined(MALLOCATOR)
void *mem= malloc(bufsz*nodesz_);
#else
void *mem= Mallocator::alloc(bufsz*nodesz_);
#endif
if(!mem)throw std::bad_alloc();
char *ptr= static_cast<char *>(mem);
first_= static_cast<bigBufferNode_t *>(mem);
bigBufferNode_t *tmp= first_;
for(size_t i= 1;i<nodesz_;++i) {

ptr+= bufsz;
tmp->next= (bigBufferNode_t*)(ptr);
tmp= tmp->next;
}
tmp->next= 0;

amem_.push_back(std::make_pair(nodesz_,mem));

return nodesz_*bufsz_;
}
}


size_t
SpecAllocator::ReleaseMemory(size_t size)
{
if(!size)return 0;

size_t memReleased=0;

if(multi_) {

if(first_) {

while(first_->next && memReleased<size) {

typeof(first_) tmp = first_;
first_ = first_->next;

#if !defined(MALLOCATOR)
free((char *)tmp - header_size());
#else
size_t bufsz = bufsz_;
if(bufsz_ < sizeof(bigBufferNode_t)) bufsz= sizeof(bigBufferNode_t);
Mallocator::free((char *)tmp - header_size(),bufsz + header_size());
#endif

memReleased+=bufsz_;
}
if(!(memReleased<size))return memReleased;
}

{
AutoLock guard(lostLock_);
while(!amem_.empty() && memReleased<size) {

typeof(first_) tmp = static_cast<typeof(first_)>(amem_.back().second);
size_t cnt= amem_.back().first;
while(tmp && memReleased<size) {

typeof(tmp) tmp1 = tmp;
tmp = tmp->next;

#if !defined(MALLOCATOR)
free((char *)tmp1 - header_size());
#else
size_t bufsz = bufsz_;
if(bufsz_ < sizeof(bigBufferNode_t)) bufsz= sizeof(bigBufferNode_t);
Mallocator::free((char *)tmp1 - header_size(),bufsz + header_size());
#endif
memReleased+=bufsz_;
--cnt;
}
if(!tmp)amem_.pop_back();
else amem_.back()= std::make_pair(cnt,tmp);
}
}
}
else {

//single thread
while(amem_.size()>1) {

#if !defined(MALLOCATOR)
free(amem_.back().second);
#else
size_t bufsz = bufsz_;
if(bufsz_ < sizeof(bigBufferNode_t)) bufsz= sizeof(bigBufferNode_t);
Mallocator::free(amem_.back().second,bufsz*nodesz_);
#endif
amem_.pop_back();
}
void *mem= amem_.back().second;
char *ptr= static_cast<char *>(mem);
first_= static_cast<bigBufferNode_t *>(mem);
bigBufferNode_t *tmp= first_;
for(size_t i= 1;i<nodesz_;++i) {

ptr+= bufsz_;
tmp->next= (bigBufferNode_t*)(ptr);
tmp= tmp->next;
}
tmp->next= 0;
/*
we don't use mem released info in single thread model
*/
}

return memReleased;
}


void *
SpecAllocator::AcquireBuffer(SpecAllocator **ppa,size_t *freemem)
{
*freemem= 0;
if(!first_) *freemem= AcquireMemory();

void *mem= first_;
first_= first_->next;

*ppa= this;

if(!multi_)
{
used_+=bufsz_;
}

return mem;
}


size_t
SpecAllocator::ReleaseBuffer(void *buf)
{
bigBufferNode_t *tmp= static_cast<bigBufferNode_t *>(buf);
if(multi_) {

char *tmp1= static_cast<char *>(buf) - header_size();
pthread_t tid= *(pthread_t *)tmp1;
if(tid != pthread_self()) {

size_t acqSize = 0;

// this chunk is not allocated by this node
//printf("SpecAllocator::ReleaseBuffer(%u,%u): this chunk is not allocated by this node but in thread %u\n",bufsz_,pthread_self(),tid);
map_t::iterator itr= foreigners_.begin();

for(;itr!=foreigners_.end();++itr)
{
if(itr->first == tid)break;
}

if(itr != foreigners_.end()) {

itr->second.first++;
tmp->next= itr->second.second;
itr->second.second= tmp;

// at last, check the magic number
if(itr->second.first > nodesz_) {

// be nice
if(!MemManagerTable::instance().LostFound(tid,
bufsz_,
itr->second.second,
itr->second.first)) {

// well, no one at home
tmp= itr->second.second;
bigBufferNode_t *tmp2= 0;
while(tmp) {

tmp1= (char *)tmp - header_size();
*(pthread_t *)tmp1= pthread_self();
tmp2= tmp;
tmp= tmp->next;
}
tmp2->next= first_;
first_= itr->second.second;
acqSize = itr->second.first*bufsz_;
}

foreigners_.erase(itr);
}
}
else {

tmp->next= 0;
foreigners_.push_back(std::make_pair(tid,std::make_pair(1,tmp)));
}

return acqSize;
}
}


tmp->next= first_;
first_= tmp;

if(!multi_)
{
used_-=bufsz_;
if(used_ == 0)ReleaseMemory(1);
return bufsz_;
}
else
{
return bufsz_;
}

}



//pthread_key_t GenAllocator::mem_key_;
//pthread_once_t GenAllocator::mem_key_once_= PTHREAD_ONCE_INIT;
//bool GenAllocator::multi_= true;


static pthread_once_t &thread_model_once()
{
static pthread_once_t _thread_model_once= (pthread_once_t)PTHREAD_ONCE_INIT;
return _thread_model_once;
}


#pragma weak setupMemoryThreadModel

static void setup_thread_model()
{
if(setupMemoryThreadModel) setupMemoryThreadModel();
}


GenAllocator::GenAllocator(size_t sz)
:
bufsz_(sz)
,maxfreememory_(32*MT_PREALLOCATE_UNITS)
,freememory_(0)
,allocator_(sz,multi()?MT_PREALLOCATE_UNITS:ST_PREALLOCATE_UNITS,multi())
{
}


GenAllocator::GenAllocator(size_t sz,size_t cnt)
:
bufsz_(sz)
,maxfreememory_(32*MT_PREALLOCATE_UNITS)
,freememory_(0)
,allocator_(sz,cnt,multi())
{
}


GenAllocator::~GenAllocator()
{
}


void
GenAllocator::setupThreadModel()
{
//printf("GenAllocator::setupThreadModel()\n");
pthread_once(&thread_model_once(),&setup_thread_model);
}


void
GenAllocator::setThreadModel(bool multithread)
{
static bool called= false;
assert(!called);
multi()= multithread;
called= true;
}


void *
GenAllocator::Alloc(size_t sz)
{
#ifdef DEBUG_BUFFER_STACK
printf("GenAllocator[%u]::Alloc(int sz= %u)\n",bufsz_,sz);
#endif

if(sz != bufsz_) {

#if !defined(MALLOCATOR)
void *p= malloc(sz);
#else
void *p = Mallocator::alloc(sz);
#endif
if(p) return p;
else throw std::bad_alloc();
}
SpecAllocator *tmp;
size_t freemem= 0;
void* mem = allocator_.AcquireBuffer(&tmp,&freemem); // can throw bad_alloc
if(multi())
{
freememory_+= freemem;
freememory_-= bufsz_;
}
return mem;
}


void
GenAllocator::Free(void *p,size_t sz)
{
#ifdef DEBUG_BUFFER_STACK
printf("GenAllocator[%u]::Free(void *p,int sz= %u)\n",bufsz_,sz);
#endif

if(!p) return;
if(sz != bufsz_)
#if !defined(MALLOCATOR)
return free(p);
#else
return Mallocator::free(p,sz);
#endif
size_t released = allocator_.ReleaseBuffer(p);
if(multi())
{
freememory_+= released;
if(freememory_>maxfreememory_)
{
freememory_-=allocator_.ReleaseMemory(freememory_- maxfreememory_);
}
}
}


void
GenAllocator::destroy()
{
pthread_key_delete(mem_key());
mem_key_once() = (pthread_once_t)PTHREAD_ONCE_INIT;
}


void
GenAllocator::destroy(void *buf)
{
map_t *m= static_cast<map_t *>(buf);
for(map_t::iterator itr= m->begin();itr!=m->end();++itr) {

itr->second->~GenAllocator();
#if !defined(MALLOCATOR)
free(itr->second);
#else
Mallocator::free(itr->second,sizeof(GenAllocator));
#endif
}
m->~map_t();
#if !defined(MALLOCATOR)
free(m);
#else
Mallocator::free(m,sizeof(map_t));
#endif
}


void
GenAllocator::mem_key_alloc()
{
pthread_key_create(&mem_key(),&destroy);
atexit(&destroy);
}



//pthread_key_t MemManager::mem_key_;
//pthread_once_t MemManager::mem_key_once_= PTHREAD_ONCE_INIT;
MemManager *MemManager::manager_= 0;
//bool MemManager::multi_= true;

#ifdef USE_NEW_INTERNAL_STATE
//size_t MemManager::maxsize_= 65536-sizeof(size_t);//65536;
//size_t MemManager::segmentsize_= 12;
#endif


MemManager::MemManager(pthread_t tid)
: maxfreememory_(0)
, freememory_(0)
,mrcnt_(0)
,mytid_(tid)
{
}


MemManager::~MemManager()
{
#ifdef USE_NEW_INTERNAL_STATE
for(seginfo_t::iterator i= seginfos_.begin();i != seginfos_.end();++i)
for(SegInfo::v_t::iterator j= (*i).v_.begin();j != (*i).v_.end();++j){

(*j)->~SpecAllocator();
#if !defined(MALLOCATOR)
free(*j);
#else
Mallocator::free(*j,sizeof(SpecAllocator));
#endif
}
#else
for(container_t::iterator i= cont_.begin();i != cont_.end();++i) {

i->second->~SpecAllocator();
#if !defined(MALLOCATOR)
free(i->second);
#else
Mallocator::free(i->second,sizeof(SpecAllocator));
#endif
}
#endif
}


#ifndef USE_NEW_INTERNAL_STATE
bool
MemManager::cmp(const content_t& lhs,const content_t& rhs)
{
return lhs.first<rhs.first;
}
#endif


SpecAllocator* MemManager::findSpecAllocator(size_t sz)
{
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];
return allocator;
}

void
MemManager::InstallNodes(bool bmulti)
{
#ifdef USE_NEW_INTERNAL_STATE

//printf("MemManager::InstallNodes(%s): start\n",multi?"TRUE":"FALSE");

size_t segbase= 12;
size_t nodesz= 128;
for(size_t i= 3;i<9;++i) {


// printf("node size: %u\n",nodesz);

size_t nextsegbase= (size_t)pow(4,i)-4;

#if 0
printf("segment %u: segment base= %u, next segment base= %u\n",
i-3,segbase,nextsegbase);
#endif

size_t segmentsize= 12;
#if 1
seginfos_.push_back(SegInfo(segbase+1,nextsegbase,(nextsegbase-segbase)/segmentsize));
#else
seginfos_.push_back(SegInfo(segbase+1,nextsegbase,(nextsegbase-segbase)/segmentsize_));
#endif
SegInfo &seginfo= seginfos_[i-3];

#if 1
for(size_t j= 0;j<segmentsize;++j) {

#if !defined(MALLOCATOR)
void *tmp= malloc(sizeof(SpecAllocator));
#else
void *tmp= Mallocator::alloc(sizeof(SpecAllocator));
#endif
if(!tmp) throw std::bad_alloc();
new(tmp)SpecAllocator(segbase + (j+1)*((nextsegbase-segbase)/segmentsize),multi()?nodesz:ST_PREALLOCATE_UNITS,multi());
// printf("%u\n",segbase + (j+1)*((nextsegbase-segbase)/segmentsize));
seginfo.v_.push_back(static_cast<SpecAllocator *>(tmp));
}
nodesz/= 2;
#else
for(size_t j= 0;j<segmentsize_;++j) {

#if !defined(MALLOCATOR)
void *tmp= malloc(sizeof(SpecAllocator));
#else
void *tmp= Mallocator::alloc(sizeof(SpecAllocator));
#endif
if(!tmp) throw std::bad_alloc();
new(tmp)SpecAllocator(segbase + (j+1)*((nextsegbase-segbase)/segmentsize_),multi_?MT_PREALLOCATE_UNITS:ST_PREALLOCATE_UNITS,multi_);
seginfo.v_.push_back(static_cast<SpecAllocator *>(tmp));
}
#endif
segbase= nextsegbase;
}

maxfreememory_ = maxsize()*seginfos_.size()*segmentsize()*2;
//fprintf(stderr,"max allocator free memory:%u\n", maxfreememory_);

//printf("MemManager::InstallNodes(): end\n\n");
#else

for(size_t i = 2; i<16; ++i) {

size_t bufsz= 2<<i;
InstallNode(bufsz,STORAGE_SIZE/bufsz);
#if 0
printf("MemManager::InstallNodes(): bufsz= %u,nodesz= %u\n",
bufsz,STORAGE_SIZE/bufsz);
#endif
}

#endif
}

size_t
MemManager::ReleaseMemory(size_t size)
{
//printf("MemManager::ReleaseMemory[%d](int size= %d)\n",++mrcnt_,size);
size_t memoryReleased = 0;
size_t tmpSize = size;
for(seginfo_t::reverse_iterator i=seginfos_.rbegin();i!=seginfos_.rend();++i)
{
SegInfo& si = *i;
for(SegInfo::v_t::reverse_iterator j=si.v_.rbegin();j!=si.v_.rend();++j)
{
size_t tmp =(*j)->ReleaseMemory(tmpSize);
tmpSize -= tmp;
memoryReleased += tmp;
if(memoryReleased>=size)
{
//printf("MemManager::ReleaseMemory[%u] 1 thread %u, memory released %u, required %u\n",++mrcnt_,pthread_self(), memoryReleased, size);
return memoryReleased;
}
}
}
//printf("MemManager::ReleaseMemory 2 thread %u, memory released %u, required %u\n",pthread_self(), memoryReleased, size);

return memoryReleased;
}

int
MemManager::AcquireBuffer(size_t sz,void **pbuf,SpecAllocator **ppnode)
{
#ifdef DEBUG_BUFFER_STACK
printf("MemManager::AcquireBuffer(int sz= %u,void **,CMemStackNode **)\n",
sz);
#endif

#ifdef USE_NEW_INTERNAL_STATE

if(seginfos_.empty()) return -1;
if(sz > maxsize()) sz= maxsize();


SpecAllocator* allocator = findSpecAllocator(sz);

size_t freemem= 0; // new memory allocated
*pbuf= allocator->AcquireBuffer(ppnode,&freemem);

if(multi())
{
freememory_+= freemem;
freememory_-= allocator->ChunkSize();
if(freememory_>maxfreememory_)
{
#if 0
printf("MemManager::AcquireMemory[%u](): free %u vs max %u\n",
++mrcnt_,freememory_,maxfreememory_);
#endif
freememory_-=ReleaseMemory(freememory_ - maxfreememory_);
}
}

return allocator->ChunkSize();

#else

if(cont_.empty()) return -1;

SpecAllocator *tmp= 0;
container_t::iterator fnd=
lower_bound(cont_.begin(),cont_.end(),std::make_pair(sz,tmp),cmp);
if(fnd == cont_.end()) --fnd;
*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...
Reply all
Reply to author
Forward
0 new messages