#if ! defined(NDEBUG)
# include <typeinfo>
# define DBG_PRINTF(mp_exp) std::printf mp_exp
#else
# define DBG_PRINTF(mp_exp)
#endif
#define ALIGN_POW2(mp_this, mp_type) ((mp_type)( \
(((std::ptrdiff_t const)(mp_this)) + 1) & (-2) \
))
#define ALIGN(mp_this, mp_type, mp_align) ((mp_type)( \
(((std::ptrdiff_t const)(mp_this)) + \
ALIGN_POW2(mp_align, std::ptrdiff_t const) - 1) \
& (-ALIGN_POW2(mp_align, std::ptrdiff_t const)) \
))
class stack_region_allocator {
unsigned char* const m_buf;
std::size_t const m_size;
std::size_t m_offset;
unsigned m_count;
public:
stack_region_allocator(
unsigned char* const buf,
std::size_t const size
) throw(std::bad_alloc)
: m_buf(buf),
m_size(size),
m_offset(0),
m_count(0) {
if (! m_buf || ! m_size) {
assert(m_buf);
assert(m_size);
throw std::bad_alloc();
}
}
~stack_region_allocator() throw() {
assert(! m_offset);
assert(! m_count);
}
public:
template<typename T>
T* allocate(
std::size_t count = 1
) throw(std::bad_alloc) {
struct offset_calc {
char pad;
T object;
};
if (! count) {
count = 1;
}
DBG_PRINTF(("typename: %s\n", typeid(T).name()));
DBG_PRINTF(("object count: %lu\n",
(unsigned long)count));
DBG_PRINTF(("object size: %lu\n",
(unsigned long)sizeof(T)));
std::size_t const alignment = offsetof(offset_calc, object);
DBG_PRINTF(("object alignment: %lu\n",
(unsigned long)alignment));
std::size_t const osize = count * sizeof(T);
DBG_PRINTF(("allocation size: %lu\n",
(unsigned long)osize));
unsigned char* const origin = m_buf + m_offset;
DBG_PRINTF(("origin buffer: %p\n", (void*)origin));
unsigned char* const align = (alignment != 1) ?
ALIGN(origin, unsigned char*, alignment) : origin;
DBG_PRINTF(("align buffer: %p\n", (void*)align));
std::ptrdiff_t const diff = align - origin;
DBG_PRINTF(("difference size: %d\n", diff));
std::size_t const offset = m_offset + diff;
DBG_PRINTF(("offset pre-size: %lu\n",
(unsigned long)offset));
if (offset + osize > m_size) {
throw std::bad_alloc();
}
m_offset = offset + osize;
DBG_PRINTF(("offset post-size: %lu\n\
--------------------------------------\n",
(unsigned long)(offset + osize)));
++m_count;
return reinterpret_cast<T*>(align);
}
void deallocate(void*) throw() {
if (! (--m_count)) {
m_offset = 0;
}
}
void reset() throw() {
m_count = 0;
m_offset = 0;
}
};
struct foo {
char c[5];
short s[2];
int i[3];
double d[3];
long double ld[2];
};
int main() {
{
unsigned char buf[1024 * 8] = { '\0' };
stack_region_allocator region(buf, sizeof(buf));
long double* ld1 = region.allocate<long double>();
char* c = region.allocate<char>(125);
long double* ld2 = region.allocate<long double>(4);
double* d = region.allocate<double>(2);
short* s = region.allocate<short>(7);
float* f = region.allocate<float>(5);
foo* _fo = region.allocate<foo>(0);
foo* _foa = region.allocate<foo>(12);
char* c2 = region.allocate<char>(13);
char* c3 = region.allocate<char>(17);
short* s1 = region.allocate<short>(3);
foo* _foa1 = region.allocate<foo>(3);
region.reset();
}
std::puts("\n\n\n____________________________________________\
_________________\npress <ENTER> to exit...");
std::getchar();
return 0;
}
________________________________________________________________________
Here is a link to the same code just in case it gets mangled by the
newsreader:
Any thoughts? Is it CRAP!?
;^o
--
Chris M. Thomasson
http://appcore.home.comcast.net
[...]
> Any thoughts? Is it CRAP!?
Here is how to use it with a non-POD type:
______________________________________________________________
#include <string>
#include <cstdio>
#include <new>
#define PRINTF_THIS(mp_type, mp_func) \
std::printf("(%p)->" mp_type "::" mp_func "\n", (void*)this)
struct foo_ctor {
std::string const m_name;
foo_ctor(std::string const& name) : m_name(name) {
PRINTF_THIS("foo_ctor", "foo_ctor()");
}
~foo_ctor() {
PRINTF_THIS("foo_ctor", "~foo_ctor()");
}
void display_name() {
PRINTF_THIS("foo_ctor", "display_name()");
std::printf("%s\n", m_name.c_str());
}
};
int main() {
{
unsigned char buf[1024 * 8] = { '\0' };
stack_region_allocator region(buf, sizeof(buf));
foo_ctor* fctor = new (region.allocate<foo_ctor>()) foo_ctor("Chris");
fctor->display_name();
fctor->~foo_ctor();
region.reset();
}
std::puts("\n\n\n____________________________________________\
_________________\npress <ENTER> to exit...");
std::getchar();
return 0;
}
______________________________________________________________
No need to call delete; just the dtor.
> ;^o