/*
===========================================================================
Copyright (C) 2000 - 2013, Raven Software, Inc.
Copyright (C) 2001 - 2013, Activision, Inc.
Copyright (C) 2013 - 2015, OpenJK contributors
This file is part of the OpenJK source code.
OpenJK is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License version 2 as
published by the Free Software Foundation.
This program 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, see .
===========================================================================
*/
////////////////////////////////////////////////////////////////////////////////////////
// RAVEN STANDARD TEMPLATE LIBRARY
// (c) 2002 Activision
//
//
// Handle 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.
//
// In addition to the standard memory pool features, this Handle Pool provides a fast
// iterator, asserts on attempting to access unused data, and a unique ID "handle" for
// the external system to use.
//
//
//
// NOTES:
//
//
//
////////////////////////////////////////////////////////////////////////////////////////
#if !defined(RATL_HANDLE_POOL_VS_INC)
#define RATL_HANDLE_POOL_VS_INC
////////////////////////////////////////////////////////////////////////////////////////
// Includes
////////////////////////////////////////////////////////////////////////////////////////
#if !defined(RATL_COMMON_INC)
#include "ratl_common.h"
#endif
#if !defined(RATL_POOL_VS_INC)
#include "pool_vs.h"
#endif
namespace ratl
{
template
class handle_pool_base : public pool_root
{
public:
typedef T TStorageTraits;
typedef typename T::TValue TTValue;
////////////////////////////////////////////////////////////////////////////////////
// Capacity Enum
////////////////////////////////////////////////////////////////////////////////////
static const int CAPACITY = T::CAPACITY;
private:
int mHandles[CAPACITY];
int mMASK_HANDLE_TO_INDEX;
int mMASK_NUM_BITS;
void IncHandle(int index)
{
mHandles[index] += (1<>= 1;
mMASK_HANDLE_TO_INDEX <<= 1;
mMASK_HANDLE_TO_INDEX |= 1;
mMASK_NUM_BITS++;
}
for (int i=0; i::clear();
// note that we do not refill the handles cause we want old handles to still be stale
for (int i=0; i::value_at_index(handle&mMASK_HANDLE_TO_INDEX);
}
////////////////////////////////////////////////////////////////////////////////////
// Accessor
////////////////////////////////////////////////////////////////////////////////////
TTValue& operator[](int i)
{
assert(is_used(i)); //typically this is a stale handle (already been freed)
return pool_root::value_at_index(i&mMASK_HANDLE_TO_INDEX);
}
bool is_used(int i) const
{
if (mHandles[i&mMASK_HANDLE_TO_INDEX]==i)
{
return pool_root::is_used_index(i&mMASK_HANDLE_TO_INDEX);
}
return false;
}
////////////////////////////////////////////////////////////////////////////////////
// Swap two items based on handle
////////////////////////////////////////////////////////////////////////////////////
void swap(int i,int j)
{
assert(is_used(i)); //typically this is a stale handle (already been freed)
assert(is_used(j)); //typically this is a stale handle (already been freed)
swap_index(handle_to_index(i),handle_to_index(j));
}
////////////////////////////////////////////////////////////////////////////////////
// The Allocator returns a handle
////////////////////////////////////////////////////////////////////////////////////
int alloc()
{
int index=pool_root::alloc_index();
return mHandles[index];
}
////////////////////////////////////////////////////////////////////////////////////
// The Allocator, with value, returns a handle
////////////////////////////////////////////////////////////////////////////////////
int alloc(const TTValue &v)
{
int index=pool_root::alloc_index(v);
return mHandles[index];
}
////////////////////////////////////////////////////////////////////////////////////
// The Deallocator, by index, not something generally needed
////////////////////////////////////////////////////////////////////////////////////
void free_index(int index)
{
pool_root::free_index(index);
IncHandle(index);
}
////////////////////////////////////////////////////////////////////////////////////
// The Deallocator, by handle
////////////////////////////////////////////////////////////////////////////////////
void free(int handle)
{
assert(is_used(handle));
free_index(handle&mMASK_HANDLE_TO_INDEX);
}
////////////////////////////////////////////////////////////////////////////////////
// The Deallocator, by pointer
////////////////////////////////////////////////////////////////////////////////////
void free(TTValue *me)
{
free_index(pointer_to_index(me));
}
////////////////////////////////////////////////////////////////////////////////////
// Convert a handle to a raw index, not generally something you should use
////////////////////////////////////////////////////////////////////////////////////
int handle_to_index(int handle) const
{
assert(is_used(handle));
return (handle&mMASK_HANDLE_TO_INDEX);
}
////////////////////////////////////////////////////////////////////////////////////
// FInd the handle for a given index, this cannot check for stale handles, so it is ill advised
////////////////////////////////////////////////////////////////////////////////////
int index_to_handle(int index) const
{
assert(index>=0 && index::is_used_index(index)); //disallowing this on stale handles
return (mHandles[index]);
}
////////////////////////////////////////////////////////////////////////////////////
// converts a T pointer to a handle, generally not something you need, cannot check for stale handles
////////////////////////////////////////////////////////////////////////////////////
int pointer_to_handle(const TTValue *me) const
{
return index_to_handle(pool_root::pointer_to_index(me));
}
////////////////////////////////////////////////////////////////////////////////////
// converts a T pointer to a handle, generally not something you need, cannot check for stale handles
////////////////////////////////////////////////////////////////////////////////////
int pointer_to_handle(const TRatlNew *me) const
{
return index_to_handle(pool_root::pointer_to_index(me));
}
////////////////////////////////////////////////////////////////////////////////////
// Get An Iterator To The Object At handle
////////////////////////////////////////////////////////////////////////////////////
typename pool_root::iterator at(int handle)
{
assert(is_used(handle));
return pool_root::at_index(handle&mMASK_HANDLE_TO_INDEX);
}
////////////////////////////////////////////////////////////////////////////////////
// Get An Iterator To The Object At handle
////////////////////////////////////////////////////////////////////////////////////
typename pool_root::const_iterator at(int handle) const
{
assert(is_used(handle));
return pool_root::at_index(handle&mMASK_HANDLE_TO_INDEX);
}
};
template
class handle_pool_vs : public handle_pool_base >
{
public:
typedef typename storage::value_semantics TStorageTraits;
typedef typename TStorageTraits::TValue TTValue;
static const int CAPACITY = ARG_CAPACITY;
handle_pool_vs() {}
};
template
class handle_pool_os : public handle_pool_base >
{
public:
typedef typename storage::object_semantics TStorageTraits;
typedef typename TStorageTraits::TValue TTValue;
static const int CAPACITY = ARG_CAPACITY;
handle_pool_os() {}
};
template
class handle_pool_is : public handle_pool_base >
{
public:
typedef typename storage::virtual_semantics TStorageTraits;
typedef typename TStorageTraits::TValue TTValue;
static const int CAPACITY = ARG_CAPACITY;
static const int MAX_CLASS_SIZE = ARG_MAX_CLASS_SIZE;
handle_pool_is() {}
};
}
#endif