Add rcNew/rcDelete, template functions that allocate/deallocate objects using rcAlloc/rcFree. (#324)

Add rcNew/rcDelete, template functions that allocate/deallocate objects using rcAlloc/rcNew.
The intention is to use these to move construction logic out of rcAllocateFooObject/rcFreeFooObject and into constructors/destructors, giving users flexbility in how objects are allocated. In particular, this allows stack allocation.
This commit is contained in:
mbabinski-at-google 2018-05-18 08:40:37 -05:00 committed by Jakob Botsch Nielsen
parent 1284a2b191
commit 9235b4a0c4
2 changed files with 57 additions and 14 deletions

View File

@ -332,6 +332,8 @@ struct rcCompactSpan
/// @ingroup recast /// @ingroup recast
struct rcCompactHeightfield struct rcCompactHeightfield
{ {
rcCompactHeightfield();
~rcCompactHeightfield();
int width; ///< The width of the heightfield. (Along the x-axis in cell units.) int width; ///< The width of the heightfield. (Along the x-axis in cell units.)
int height; ///< The height of the heightfield. (Along the z-axis in cell units.) int height; ///< The height of the heightfield. (Along the z-axis in cell units.)
int spanCount; ///< The number of spans in the heightfield. int spanCount; ///< The number of spans in the heightfield.

View File

@ -23,11 +23,34 @@
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h> #include <stdio.h>
#include <stdarg.h> #include <stdarg.h>
#include <new>
#include "Recast.h" #include "Recast.h"
#include "RecastAlloc.h" #include "RecastAlloc.h"
#include "RecastAssert.h" #include "RecastAssert.h"
namespace
{
/// Allocates and constructs an object of the given type, returning a pointer.
/// TODO: Support constructor args.
/// @param[in] hint Hint to the allocator.
template <typename T>
T* rcNew(rcAllocHint hint) {
T* ptr = (T*)rcAlloc(sizeof(T), hint);
::new(rcNewTag(), (void*)ptr) T();
return ptr;
}
/// Destroys and frees an object allocated with rcNew.
/// @param[in] ptr The object pointer to delete.
template <typename T>
void rcDelete(T* ptr) {
if (ptr) {
ptr->~T();
rcFree((void*)ptr);
}
}
} // namespace
float rcSqrt(float x) float rcSqrt(float x)
{ {
return sqrtf(x); return sqrtf(x);
@ -73,7 +96,7 @@ void rcContext::log(const rcLogCategory category, const char* format, ...)
rcHeightfield* rcAllocHeightfield() rcHeightfield* rcAllocHeightfield()
{ {
return new (rcAlloc(sizeof(rcHeightfield), RC_ALLOC_PERM)) rcHeightfield; return rcNew<rcHeightfield>(RC_ALLOC_PERM);
} }
rcHeightfield::rcHeightfield() rcHeightfield::rcHeightfield()
@ -104,26 +127,44 @@ rcHeightfield::~rcHeightfield()
void rcFreeHeightField(rcHeightfield* hf) void rcFreeHeightField(rcHeightfield* hf)
{ {
if (!hf) return; rcDelete(hf);
hf->~rcHeightfield();
rcFree(hf);
} }
rcCompactHeightfield* rcAllocCompactHeightfield() rcCompactHeightfield* rcAllocCompactHeightfield()
{ {
rcCompactHeightfield* chf = (rcCompactHeightfield*)rcAlloc(sizeof(rcCompactHeightfield), RC_ALLOC_PERM); return rcNew<rcCompactHeightfield>(RC_ALLOC_PERM);
memset(chf, 0, sizeof(rcCompactHeightfield));
return chf;
} }
void rcFreeCompactHeightfield(rcCompactHeightfield* chf) void rcFreeCompactHeightfield(rcCompactHeightfield* chf)
{ {
if (!chf) return; rcDelete(chf);
rcFree(chf->cells); }
rcFree(chf->spans);
rcFree(chf->dist); rcCompactHeightfield::rcCompactHeightfield()
rcFree(chf->areas); : width(0),
rcFree(chf); height(0),
spanCount(0),
walkableHeight(0),
walkableClimb(0),
borderSize(0),
maxDistance(0),
maxRegions(0),
bmin(),
bmax(),
cs(0),
ch(0),
cells(0),
spans(0),
dist(0),
areas(0)
{
}
rcCompactHeightfield::~rcCompactHeightfield()
{
rcFree(cells);
rcFree(spans);
rcFree(dist);
rcFree(areas);
} }
rcHeightfieldLayerSet* rcAllocHeightfieldLayerSet() rcHeightfieldLayerSet* rcAllocHeightfieldLayerSet()