dyn_array: added matrix allocator for convenience. renamed to "allocators.cpp" (now contains several of them)

LOSMananager: uses matrix allocator; free them in dtor

This was SVN commit r2914.
This commit is contained in:
janwas 2005-10-12 15:51:26 +00:00
parent 4285883f3d
commit 3c2d38502c
3 changed files with 98 additions and 15 deletions

View File

@ -4,6 +4,10 @@
#include "dyn_array.h"
//-----------------------------------------------------------------------------
// expandable array
//-----------------------------------------------------------------------------
static const size_t page_size = sysconf(_SC_PAGE_SIZE);
static bool is_page_multiple(uintptr_t x)
@ -92,8 +96,9 @@ static int mem_protect(u8* p, size_t size, int prot)
return mprotect(p, size, prot);
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// API
int da_alloc(DynArray* da, size_t max_size)
{
@ -222,8 +227,9 @@ int da_append(DynArray* da, const void* data, size_t size)
//-----------------------------------------------------------------------------
// pool allocator
//-----------------------------------------------------------------------------
// design goals: O(1) alloc and free; doesn't preallocate the entire pool;
// returns sequential addresses.
//
@ -334,6 +340,65 @@ void pool_free(Pool* p, void* el)
}
//-----------------------------------------------------------------------------
// matrix allocator
//-----------------------------------------------------------------------------
// takes care of the dirty work of allocating 2D matrices:
// - aligns data
// - only allocates one memory block, which is more efficient than
// malloc/new for each row.
// allocate a 2D cols x rows matrix of <el_size> byte cells.
// this must be freed via matrix_free. returns 0 if out of memory.
//
// the returned pointer should be cast to the target type (e.g. int**) and
// can then be accessed by matrix[col][row].
void** matrix_alloc(uint cols, uint rows, size_t el_size)
{
const size_t initial_align = 64;
// note: no provision for padding rows. this is a bit more work and
// if el_size isn't a power-of-2, performance is going to suck anyway.
// otherwise, the initial alignment will take care of it.
const size_t ptr_array_size = cols*sizeof(void*);
const size_t row_size = cols*el_size;
const size_t data_size = rows*row_size;
const size_t total_size = ptr_array_size + initial_align + data_size;
void* p = malloc(total_size);
if(!p)
return 0;
uintptr_t data_addr = (uintptr_t)p + ptr_array_size + initial_align;
data_addr -= data_addr % initial_align;
// alignment check didn't set address to before allocation
debug_assert(data_addr >= (uintptr_t)p+ptr_array_size);
void** ptr_array = (void**)p;
for(uint i = 0; i < cols; i++)
{
ptr_array[i] = (void*)data_addr;
data_addr += row_size;
}
// didn't overrun total allocation
debug_assert(data_addr <= (uintptr_t)p+total_size);
return ptr_array;
}
// free the given matrix (allocated by matrix_alloc). no-op if matrix == 0.
// callers will likely want to pass variables of a different type
// (e.g. int**); they must be cast to void**.
void matrix_free(void** matrix)
{
free(matrix);
}
//-----------------------------------------------------------------------------
// built-in self test
//-----------------------------------------------------------------------------

View File

@ -72,3 +72,26 @@ extern void* pool_alloc(Pool* p);
// make <el> available for reuse in the given pool.
extern void pool_free(Pool* p, void* el);
//
// matrix allocator
//
// takes care of the dirty work of allocating 2D matrices:
// - aligns data
// - only allocates one memory block, which is more efficient than
// malloc/new for each row.
// allocate a 2D cols x rows matrix of <el_size> byte cells.
// this must be freed via matrix_free. returns 0 if out of memory.
//
// the returned pointer should be cast to the target type (e.g. int**) and
// can then be accessed by matrix[col][row].
//
extern void** matrix_alloc(uint cols, uint rows, size_t el_size);
// free the given matrix (allocated by matrix_alloc). no-op if matrix == 0.
// callers will likely want to pass variables of a different type
// (e.g. int**); they must be cast to void**.
extern void matrix_free(void** matrix);

View File

@ -10,6 +10,7 @@
#include "Unit.h"
#include "Bound.h"
#include "Model.h"
#include "dyn_array.h"
using namespace std;
@ -19,6 +20,10 @@ CLOSManager::CLOSManager() : m_LOSSetting(0), m_Explored(0), m_Visible(0)
CLOSManager::~CLOSManager()
{
matrix_free((void**)m_Explored);
m_Explored = 0;
matrix_free((void**)m_Visible);
m_Visible = 0;
}
void CLOSManager::Initialize(uint losSetting)
@ -27,21 +32,12 @@ void CLOSManager::Initialize(uint losSetting)
int tilesPerSide = terrain->GetVerticesPerSide() - 1;
// Create the LOS data arrays
m_Explored = new int*[tilesPerSide];
for(int i=0; i<tilesPerSide; i++)
{
m_Explored[i] = new int[tilesPerSide];
}
m_Visible = new int*[tilesPerSide];
for(int i=0; i<tilesPerSide; i++)
{
m_Visible[i] = new int[tilesPerSide];
}
m_Explored = (int**)matrix_alloc(tilesPerSide, tilesPerSide, sizeof(int));
m_Visible = (int**)matrix_alloc(tilesPerSide, tilesPerSide, sizeof(int));
// TODO: This memory should be freed somewhere when the engine supports
// multiple sessions without restarting the program.
// JW: currently free it in the dtor
// Clear everything to unexplored
for(int x=0; x<tilesPerSide; x++)
@ -51,7 +47,6 @@ void CLOSManager::Initialize(uint losSetting)
// Just Update() to set the visible array and also mark currently visible tiles as explored.
// NOTE: this will have to be changed if we decide to use incremental LOS
Update();
// Set special LOS setting