git-svn-id: svn://svn.code.sf.net/p/actiongame/code/trunk/ac@2551 e016b1c5-ed68-44aa-a2f7-31cac88cffde
155 lines
3.6 KiB
C++
155 lines
3.6 KiB
C++
template<class T> struct modelcacheentry
|
|
{
|
|
typedef modelcacheentry<T> entry;
|
|
|
|
T *prev, *next, *nextalloc;
|
|
size_t size;
|
|
bool locked;
|
|
|
|
modelcacheentry(T *prev = NULL, T *next = NULL) : prev(prev), next(next), nextalloc(NULL), size(0), locked(false) {}
|
|
|
|
bool empty() const
|
|
{
|
|
return prev==next;
|
|
}
|
|
|
|
void linkbefore(T *pos)
|
|
{
|
|
next = pos;
|
|
prev = pos->entry::prev;
|
|
prev->entry::next = (T *)this;
|
|
next->entry::prev = (T *)this;
|
|
}
|
|
|
|
void linkafter(T *pos)
|
|
{
|
|
next = pos->entry::next;
|
|
prev = pos;
|
|
prev->entry::next = (T *)this;
|
|
next->entry::prev = (T *)this;
|
|
}
|
|
|
|
void unlink()
|
|
{
|
|
prev->entry::next = next;
|
|
next->entry::prev = prev;
|
|
prev = next = (T *)this;
|
|
}
|
|
|
|
void *getdata()
|
|
{
|
|
return (T *)this + 1;
|
|
}
|
|
};
|
|
|
|
template<class T> struct modelcachelist : modelcacheentry<T>
|
|
{
|
|
typedef modelcacheentry<T> entry;
|
|
|
|
modelcachelist() : entry((T *)this, (T *)this) {}
|
|
|
|
T *start() { return entry::next; }
|
|
T *end() { return (T *)this; }
|
|
|
|
void addfirst(entry *e)
|
|
{
|
|
e->linkafter((T *)this);
|
|
}
|
|
|
|
void addlast(entry *e)
|
|
{
|
|
e->linkbefore((T *)this);
|
|
}
|
|
|
|
void removefirst()
|
|
{
|
|
if(!entry::empty()) entry::next->unlink();
|
|
}
|
|
|
|
void removelast()
|
|
{
|
|
if(!entry::empty()) entry::prev->unlink();
|
|
}
|
|
};
|
|
|
|
struct modelcache
|
|
{
|
|
struct entry : modelcacheentry<entry> {};
|
|
|
|
uchar *buf;
|
|
size_t size;
|
|
entry *curalloc;
|
|
|
|
modelcache(size_t size = 0) : buf(size ? new uchar[size] : NULL), size(size), curalloc(NULL) {}
|
|
~modelcache() { DELETEA(buf); }
|
|
|
|
void resize(size_t nsize)
|
|
{
|
|
if(curalloc)
|
|
{
|
|
for(curalloc = (entry *)buf; curalloc; curalloc = curalloc->nextalloc) curalloc->unlink();
|
|
}
|
|
DELETEA(buf);
|
|
buf = nsize ? new uchar[nsize] : 0;
|
|
size = nsize;
|
|
}
|
|
|
|
template<class T>
|
|
T *allocate(size_t reqsize)
|
|
{
|
|
reqsize += sizeof(T);
|
|
if(reqsize > size) return NULL;
|
|
|
|
if(!curalloc)
|
|
{
|
|
curalloc = (entry *)buf;
|
|
curalloc->size = reqsize;
|
|
curalloc->locked = false;
|
|
curalloc->nextalloc = NULL;
|
|
return (T *)curalloc;
|
|
}
|
|
|
|
if(curalloc) for(bool failed = false;;)
|
|
{
|
|
uchar *nextfree = curalloc ? (uchar *)curalloc + curalloc->size : (uchar *)buf;
|
|
entry *nextused = curalloc ? curalloc->nextalloc : (entry *)buf;
|
|
for(;;)
|
|
{
|
|
if(!nextused)
|
|
{
|
|
if(size_t(&buf[size] - nextfree) >= reqsize) goto success;
|
|
break;
|
|
}
|
|
else if(size_t((uchar *)nextused - nextfree) >= reqsize) goto success;
|
|
else if(nextused->locked) break;
|
|
nextused->unlink();
|
|
nextused = nextused->nextalloc;
|
|
}
|
|
if(curalloc) curalloc->nextalloc = nextused;
|
|
else if(failed) { curalloc = nextused; break; }
|
|
else failed = true;
|
|
curalloc = nextused;
|
|
continue;
|
|
|
|
success:
|
|
entry *result = (entry *)nextfree;
|
|
result->size = reqsize;
|
|
result->locked = false;
|
|
result->nextalloc = nextused;
|
|
if(curalloc) curalloc->nextalloc = result;
|
|
curalloc = result;
|
|
return (T *)curalloc;
|
|
}
|
|
|
|
curalloc = (entry *)buf;
|
|
return NULL;
|
|
}
|
|
|
|
template<class T>
|
|
void release(modelcacheentry<T> *e)
|
|
{
|
|
e->unlink();
|
|
}
|
|
};
|
|
|