mirror of
https://github.com/ioquake/jedi-academy.git
synced 2024-11-29 23:41:52 +00:00
570 lines
17 KiB
C++
570 lines
17 KiB
C++
////////////////////////////////////////////////////////////////////////////////////////
|
|
// RAVEN STANDARD TEMPLATE LIBRARY
|
|
// (c) 2002 Activision
|
|
//
|
|
//
|
|
// Memory Pool
|
|
// -----------
|
|
// The memory pool class is a simple routine for constant time allocation and deallocation
|
|
// from a fixed size pool of objects. The class uses a simple array to hold the actual
|
|
// data, a queue for the free list, and a bit field to mark which spots in the array
|
|
// are allocated.
|
|
//
|
|
//
|
|
//
|
|
// NOTES:
|
|
//
|
|
//
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////////////////
|
|
#if !defined(RATL_POOL_VS_INC)
|
|
#define RATL_POOL_VS_INC
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////
|
|
// Includes
|
|
////////////////////////////////////////////////////////////////////////////////////////
|
|
#if !defined(RATL_COMMON_INC)
|
|
#include "ratl_common.h"
|
|
#endif
|
|
#if !defined(RATL_QUEUE_VS_INC)
|
|
#include "queue_vs.h"
|
|
#endif
|
|
|
|
namespace ratl
|
|
{
|
|
|
|
// fixme, this could be made more efficient by keepingtrack of the highest slot ever used
|
|
// then there is no need to fill the free list
|
|
template <class T>
|
|
class pool_root : public ratl_base
|
|
{
|
|
public:
|
|
typedef T TStorageTraits;
|
|
typedef typename T::TValue TTValue;
|
|
////////////////////////////////////////////////////////////////////////////////////
|
|
// Capacity Enum
|
|
////////////////////////////////////////////////////////////////////////////////////
|
|
enum
|
|
{
|
|
CAPACITY = T::CAPACITY
|
|
};
|
|
private:
|
|
////////////////////////////////////////////////////////////////////////////////////
|
|
// Data
|
|
////////////////////////////////////////////////////////////////////////////////////
|
|
array_base<TStorageTraits> mData;
|
|
queue_vs<int, CAPACITY> mFree;
|
|
bits_base<CAPACITY> mUsed;
|
|
int mSize;
|
|
|
|
|
|
void FillFreeList()
|
|
{
|
|
mFree.clear();
|
|
int i;
|
|
for (i=0;i<CAPACITY;i++)
|
|
{
|
|
mFree.push(i);
|
|
}
|
|
}
|
|
int alloc_low()
|
|
{
|
|
assert(mSize<CAPACITY);
|
|
assert(!mUsed[mFree.top()]);
|
|
|
|
int NextIndex = mFree.top(); // Get The First Available Location
|
|
|
|
mUsed.set_bit(NextIndex);
|
|
mFree.pop();
|
|
mSize ++;
|
|
return NextIndex;
|
|
}
|
|
public:
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////
|
|
// Constructor
|
|
////////////////////////////////////////////////////////////////////////////////////
|
|
pool_root() : mSize(0)
|
|
{
|
|
FillFreeList();
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////
|
|
// The Number Of Objects Allocated
|
|
////////////////////////////////////////////////////////////////////////////////////
|
|
int size() const
|
|
{
|
|
return (mSize);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////
|
|
// Check To See If This Memory Pool Is Empty
|
|
////////////////////////////////////////////////////////////////////////////////////
|
|
bool empty() const
|
|
{
|
|
return (mSize==0);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////
|
|
// Check To See If This Memory Pool Is Full
|
|
////////////////////////////////////////////////////////////////////////////////////
|
|
bool full() const
|
|
{
|
|
return (mSize==CAPACITY);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////
|
|
// Constant Accessor
|
|
////////////////////////////////////////////////////////////////////////////////////
|
|
const TTValue& value_at_index(int i) const
|
|
{
|
|
assert(mUsed[i]);
|
|
return (mData[i]);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////
|
|
// Accessor
|
|
////////////////////////////////////////////////////////////////////////////////////
|
|
TTValue& value_at_index(int i)
|
|
{
|
|
assert(mUsed[i]);
|
|
return (mData[i]);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////
|
|
// Clear - Removes all allocation information
|
|
////////////////////////////////////////////////////////////////////////////////////
|
|
void clear()
|
|
{
|
|
mSize = 0;
|
|
mUsed.clear();
|
|
mData.clear();
|
|
FillFreeList();
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////
|
|
// Check If An Index Has Been Allocated
|
|
////////////////////////////////////////////////////////////////////////////////////
|
|
bool is_used_index(int i) const
|
|
{
|
|
return mUsed[i];
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////
|
|
// Convert a pointer back to an index
|
|
////////////////////////////////////////////////////////////////////////////////////
|
|
int pointer_to_index(const TTValue *me) const
|
|
{
|
|
assert(mSize>0);
|
|
|
|
int index=mData.pointer_to_index(me);
|
|
|
|
assert(index>=0 && index<CAPACITY);
|
|
assert(mUsed[index]); // I am disallowing obtaining the index of a freed item
|
|
|
|
return index;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////
|
|
// Convert a pointer back to an index
|
|
////////////////////////////////////////////////////////////////////////////////////
|
|
int pointer_to_index(const TRatlNew *me) const
|
|
{
|
|
assert(mSize>0);
|
|
|
|
int index=mData.pointer_to_index(me);
|
|
|
|
assert(index>=0 && index<CAPACITY);
|
|
assert(mUsed[index]); // I am disallowing obtaining the index of a freed item
|
|
|
|
return index;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////
|
|
// Swap two items based on index
|
|
////////////////////////////////////////////////////////////////////////////////////
|
|
void swap_index(int i,int j)
|
|
{
|
|
assert(i>=0 && i<CAPACITY);
|
|
assert(j>=0 && j<CAPACITY);
|
|
mData.swap(i,j);
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////
|
|
// The Allocator
|
|
////////////////////////////////////////////////////////////////////////////////////
|
|
int alloc_index()
|
|
{
|
|
int NextIndex = alloc_low();
|
|
mData.construct(NextIndex);
|
|
return NextIndex;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////
|
|
// The Allocator
|
|
////////////////////////////////////////////////////////////////////////////////////
|
|
int alloc_index(const TTValue &v)
|
|
{
|
|
int NextIndex = alloc_low();
|
|
mData.construct(NextIndex,v);
|
|
return NextIndex;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////
|
|
// The Allocator
|
|
////////////////////////////////////////////////////////////////////////////////////
|
|
TRatlNew * alloc_raw()
|
|
{
|
|
int NextIndex = alloc_low();
|
|
return mData.alloc_raw(NextIndex);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////
|
|
// The Deallocator
|
|
////////////////////////////////////////////////////////////////////////////////////
|
|
void free_index(int i)
|
|
{
|
|
assert(mSize>0);
|
|
assert(i>=0 && i<CAPACITY);
|
|
assert(mUsed[i]);
|
|
|
|
mData.destruct(i);
|
|
|
|
mUsed.clear_bit(i);
|
|
mFree.push(i);
|
|
mSize --;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////
|
|
// The Deallocator
|
|
////////////////////////////////////////////////////////////////////////////////////
|
|
void free(TTValue *me)
|
|
{
|
|
free(pointer_to_index(me));
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////
|
|
// Iterator
|
|
////////////////////////////////////////////////////////////////////////////////////
|
|
class const_iterator;
|
|
class iterator
|
|
{
|
|
friend class pool_root<T>;
|
|
friend class const_iterator;
|
|
int mIndex;
|
|
pool_root<T>* mOwner;
|
|
public:
|
|
// Constructors
|
|
//--------------
|
|
iterator() : mOwner(0)
|
|
{}
|
|
iterator(pool_root<T>* p, int index) : mOwner(p), mIndex(index)
|
|
{}
|
|
iterator(const iterator &t) : mOwner(t.mOwner), mIndex(t.mIndex)
|
|
{}
|
|
|
|
// Assignment Operator
|
|
//---------------------
|
|
void operator= (const iterator &t)
|
|
{
|
|
mOwner = t.mOwner;
|
|
mIndex = t.mIndex;
|
|
}
|
|
|
|
// Equality Operators
|
|
//--------------------
|
|
bool operator!=(const iterator& t) {assert(mOwner && mOwner==t.mOwner); return (mIndex!=t.mIndex);}
|
|
bool operator==(const iterator& t) {assert(mOwner && mOwner==t.mOwner); return (mIndex==t.mIndex);}
|
|
|
|
// Dereference Operators
|
|
//----------------------
|
|
TTValue& operator* () const {assert(mOwner && mOwner->is_used_index(mIndex)); return (mOwner->mData[mIndex]);}
|
|
TTValue* operator->() const {assert(mOwner && mOwner->is_used_index(mIndex)); return (&mOwner->mData[mIndex]);}
|
|
|
|
// Handle & Index Access
|
|
//-----------------------
|
|
int index() {assert(mOwner && mOwner->is_used_index(mIndex)); return mIndex;}
|
|
|
|
// Inc Operator
|
|
//-------------
|
|
iterator operator++(int) // postfix
|
|
{
|
|
assert(mIndex>=0&&mIndex<CAPACITY); // this typically means you did end()++
|
|
assert(mOwner && mOwner->is_used_index(mIndex));
|
|
|
|
iterator ret(*this);
|
|
mIndex = mOwner->mUsed.next_bit(mIndex+1);
|
|
return ret;
|
|
}
|
|
// Inc Operator
|
|
//-------------
|
|
iterator operator++() // prefix
|
|
{
|
|
assert(mIndex>=0&&mIndex<CAPACITY); // this typically means you did end()++
|
|
assert(mOwner && mOwner->is_used_index(mIndex));
|
|
mIndex = mOwner->mUsed.next_bit(mIndex+1);
|
|
return *this;
|
|
}
|
|
};
|
|
friend class iterator;
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////
|
|
// Iterator
|
|
////////////////////////////////////////////////////////////////////////////////////
|
|
class const_iterator
|
|
{
|
|
int mIndex;
|
|
const pool_root<T>* mOwner;
|
|
public:
|
|
// Constructors
|
|
//--------------
|
|
const_iterator() : mOwner(0)
|
|
{}
|
|
const_iterator(const pool_root<T>* p, int index) : mOwner(p), mIndex(index)
|
|
{}
|
|
const_iterator(const iterator &t) : mOwner(t.mOwner), mIndex(t.mIndex)
|
|
{}
|
|
const_iterator(const const_iterator &t) : mOwner(t.mOwner), mIndex(t.mIndex)
|
|
{}
|
|
|
|
// Equality Operators
|
|
//--------------------
|
|
bool operator!=(const const_iterator& t) const {assert(mOwner && mOwner==t.mOwner); return (mIndex!=t.mIndex);}
|
|
bool operator==(const const_iterator& t) const {assert(mOwner && mOwner==t.mOwner); return (mIndex==t.mIndex);}
|
|
bool operator!=(const iterator& t) const {assert(mOwner && mOwner==t.mOwner); return (mIndex!=t.mIndex);}
|
|
bool operator==(const iterator& t) const {assert(mOwner && mOwner==t.mOwner); return (mIndex==t.mIndex);}
|
|
|
|
// Dereference Operators
|
|
//----------------------
|
|
const TTValue& operator* () const {assert(mOwner && mOwner->is_used_index(mIndex)); return (mOwner->mData[mIndex]);}
|
|
const TTValue* operator->() const {assert(mOwner && mOwner->is_used_index(mIndex)); return (&mOwner->mData[mIndex]);}
|
|
|
|
// Handle & Index Access
|
|
//-----------------------
|
|
int index() const {assert(mOwner && mOwner->is_used_index(mIndex)); return mIndex;}
|
|
|
|
// Inc Operator
|
|
//-------------
|
|
const_iterator operator++(int) // postfix
|
|
{
|
|
assert(mIndex>=0&&mIndex<CAPACITY); // this typically means you did end()++
|
|
assert(mOwner && mOwner->is_used_index(mIndex));
|
|
|
|
const_iterator ret(*this);
|
|
mIndex = mOwner->mUsed.next_bit(mIndex+1);
|
|
return ret;
|
|
}
|
|
// Inc Operator
|
|
//-------------
|
|
const_iterator operator++() // prefix
|
|
{
|
|
assert(mIndex>=0&&mIndex<CAPACITY); // this typically means you did end()++
|
|
assert(mOwner && mOwner->is_used_index(mIndex));
|
|
mIndex = mOwner->mUsed.next_bit(mIndex+1);
|
|
return *this;
|
|
}
|
|
};
|
|
friend class const_iterator;
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////
|
|
// Get An Iterator To The First Allocated Memory Block
|
|
////////////////////////////////////////////////////////////////////////////////////
|
|
iterator begin()
|
|
{
|
|
int idx=mUsed.next_bit(0);
|
|
return iterator(this,idx); // Find The First Allocated
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////
|
|
// Get An Iterator To The Object At index
|
|
////////////////////////////////////////////////////////////////////////////////////
|
|
iterator at_index(int index)
|
|
{
|
|
assert(mUsed[index]); // disallow iterators to non alloced things
|
|
return iterator(this, index);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////
|
|
// Get An Iterator To The End Of The Memroy (One Step Beyond)
|
|
////////////////////////////////////////////////////////////////////////////////////
|
|
iterator end()
|
|
{
|
|
return iterator(this, CAPACITY);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////
|
|
// Get An Iterator To The First Allocated Memory Block
|
|
////////////////////////////////////////////////////////////////////////////////////
|
|
const_iterator begin() const
|
|
{
|
|
int idx=mUsed.next_bit(0);
|
|
return iterator(this,idx); // Find The First Allocated
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////
|
|
// Get An Iterator To The Object At index
|
|
////////////////////////////////////////////////////////////////////////////////////
|
|
const_iterator at_index(int index) const
|
|
{
|
|
assert(mUsed[index]); // disallow iterators to non alloced things
|
|
return iterator(this, index);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////
|
|
// Get An Iterator To The End Of The Memroy (One Step Beyond)
|
|
////////////////////////////////////////////////////////////////////////////////////
|
|
const_iterator end() const
|
|
{
|
|
return iterator(this, CAPACITY);
|
|
}
|
|
|
|
template<class CAST_TO>
|
|
CAST_TO *verify_alloc(CAST_TO *p) const
|
|
{
|
|
return mData.verify_alloc(p);
|
|
}
|
|
};
|
|
|
|
/*
|
|
pool_base, base class for the pools
|
|
|
|
operations:
|
|
|
|
size()
|
|
empty()
|
|
full()
|
|
clear() op[]
|
|
at_index() op[]
|
|
at_index() const
|
|
index pointer_to_index(ptr)
|
|
index alloc_index() alloc()
|
|
index alloc_index(ref) alloc()
|
|
ptr alloc_raw()
|
|
free_index(index)
|
|
free(ptr)
|
|
is_used_index(index)
|
|
|
|
*/
|
|
|
|
template <class T>
|
|
class pool_base : public pool_root<T>
|
|
{
|
|
public:
|
|
typedef typename T::TValue TTValue;
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////
|
|
// Constant Accessor
|
|
////////////////////////////////////////////////////////////////////////////////////
|
|
const TTValue& operator[](int i) const
|
|
{
|
|
return this->value_at_index(i);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////
|
|
// Accessor
|
|
////////////////////////////////////////////////////////////////////////////////////
|
|
TTValue& operator[](int i)
|
|
{
|
|
return this->value_at_index(i);
|
|
}
|
|
|
|
bool is_used(int i) const
|
|
{
|
|
return this->is_used_index(i);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////
|
|
// Swap two items based on index
|
|
////////////////////////////////////////////////////////////////////////////////////
|
|
void swap(int i,int j)
|
|
{
|
|
this->swap_index(i,j);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////
|
|
// The Allocator returns an index
|
|
////////////////////////////////////////////////////////////////////////////////////
|
|
int alloc()
|
|
{
|
|
return this->alloc_index();
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////
|
|
// The Allocator returns an index
|
|
////////////////////////////////////////////////////////////////////////////////////
|
|
int alloc(const TTValue &v)
|
|
{
|
|
return this->alloc_index(v);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////
|
|
// The Deallocator
|
|
////////////////////////////////////////////////////////////////////////////////////
|
|
void free(int i)
|
|
{
|
|
this->free_index(i);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////
|
|
// Get An Iterator To The Object At index
|
|
////////////////////////////////////////////////////////////////////////////////////
|
|
typename pool_root<T>::iterator at(int index)
|
|
{
|
|
return this->at_index(index);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////
|
|
// Get An Iterator To The Object At index
|
|
////////////////////////////////////////////////////////////////////////////////////
|
|
typename pool_root<T>::const_iterator at(int index) const
|
|
{
|
|
return this->at_index(index);
|
|
}
|
|
};
|
|
|
|
template<class T, int ARG_CAPACITY>
|
|
class pool_vs : public pool_base<storage::value_semantics<T,ARG_CAPACITY> >
|
|
{
|
|
public:
|
|
typedef typename storage::value_semantics<T,ARG_CAPACITY> TStorageTraits;
|
|
typedef typename TStorageTraits::TValue TTValue;
|
|
enum
|
|
{
|
|
CAPACITY = ARG_CAPACITY
|
|
};
|
|
pool_vs() {}
|
|
};
|
|
|
|
template<class T, int ARG_CAPACITY>
|
|
class pool_os : public pool_base<storage::object_semantics<T,ARG_CAPACITY> >
|
|
{
|
|
public:
|
|
typedef typename storage::object_semantics<T,ARG_CAPACITY> TStorageTraits;
|
|
typedef typename TStorageTraits::TValue TTValue;
|
|
enum
|
|
{
|
|
CAPACITY = ARG_CAPACITY
|
|
};
|
|
pool_os() {}
|
|
};
|
|
|
|
template<class T, int ARG_CAPACITY, int ARG_MAX_CLASS_SIZE>
|
|
class pool_is : public pool_base<storage::virtual_semantics<T,ARG_CAPACITY,ARG_MAX_CLASS_SIZE> >
|
|
{
|
|
public:
|
|
typedef typename storage::virtual_semantics<T,ARG_CAPACITY,ARG_MAX_CLASS_SIZE> TStorageTraits;
|
|
typedef typename TStorageTraits::TValue TTValue;
|
|
enum
|
|
{
|
|
CAPACITY = ARG_CAPACITY,
|
|
MAX_CLASS_SIZE = ARG_MAX_CLASS_SIZE
|
|
};
|
|
pool_is() {}
|
|
};
|
|
|
|
}
|
|
#endif
|