Scroll to navigation

stack_allocator(7rheolef) rheolef-7.0 stack_allocator(7rheolef)

NAME

stack_allocator - stack-based allocator

DESCRIPTION

Stack-based allocator, conform to the STL specification of allocators. Designed to use stack-based data passed as a parameter to the allocator constructor. Does not "free" the memory. Assumes that if the allocator is copied, stack memory is cleared and new allocations begin at the bottom of the stack again.

Also works with any memory buffer, including heap memory. If the caller passes in heap memory, the caller is responsible for freeing the memory.

This allocator handles a limited area of memory: if this limit is reached, a "std::bad_alloc" exception is emmited. For a non-limited memory handler in the same spirit, see "heap_allocator"(9).

EXAMPLE


const size_t stack_size = 1024;
vector<unsigned char> stack (stack_size);
stack_allocator<double> stack_alloc (stack.begin().operator->(), stack.size());
typedef map <size_t, double, less<size_t>, stack_allocator<pair<size_t,double> > > map_type;
map_type a (less<size_t>(), stack_alloc);
a.insert (make_pair (0, 3.14));
a.insert (make_pair (1, 1.17));
for (map_type::iterator iter = a.begin(), last = a.end(); iter != last; iter++) {
cout << (*iter).first << " " << (*iter).second << endl;
}

IMPLEMENTATION

template <typename T>
class stack_allocator {
protected:

struct handler_type; // forward declaration: public: // typedefs:
typedef size_t size_type;
typedef std::ptrdiff_t difference_type;
typedef T* pointer;
typedef const T* const_pointer;
typedef T& reference;
typedef const T& const_reference;
typedef T value_type; // constructors:
stack_allocator() throw()
: handler (new handler_type)
{
}
stack_allocator (unsigned char* stack, size_t stack_size) throw()
: handler (new handler_type (stack, stack_size))
{
trace_macro ("stack_allocator cstor");
}
stack_allocator (const stack_allocator& sa) throw()
: handler (sa.handler)
{
++handler->reference_count;
}
template <typename U>
stack_allocator (const stack_allocator<U>& sa) throw()
: handler ((typename stack_allocator<T>::handler_type*)(sa.handler))
{
++handler->reference_count;
}
~stack_allocator() throw()
{
trace_macro ("stack_allocator dstor");
check_macro (handler != NULL, "unexpected null mem_info");
if (--handler->reference_count == 0) delete handler;
}
// Rebind to allocators of other types
template <typename U>
struct rebind {
typedef stack_allocator<U> other;
}; // assignment:
stack_allocator& operator= (const stack_allocator& sa)
{
handler = sa.handler;
++handler->reference_count;
return *this;
} // utility functions:
pointer address (reference r) const { return &r; }
const_pointer address (const_reference c) const { return &c; }
size_type max_size() const { return std::numeric_limits<size_t>::max() / sizeof(T); } // in-place construction/destruction
void construct (pointer p, const_reference c)
{
// placement new operator:
new( reinterpret_cast<void*>(p) ) T(c);
}
// C++ 2011: default construct a value of type T at the location referenced by p
void construct (pointer p) { new ( reinterpret_cast<void*>(p) ) T(); }
void destroy (pointer p)
{
// call destructor directly:
(p)->~T();
} // allocate raw memory
pointer allocate (size_type n, const void* = NULL)
{
trace_macro ("allocate "<<n<<" type " << typename_macro(T));
check_macro (handler->stack != NULL, "unexpected null stack");
void* p = handler->stack + handler->allocated_size;
handler->allocated_size += n*sizeof(T);
if (handler->allocated_size + 1 > handler->max_size) {
trace_macro ("stack is full: throwing...");
throw std::bad_alloc();
}
return pointer (p);
}
void deallocate (pointer p, size_type n)
{
trace_macro ("deallocate "<<n<<" type "<<typename_macro(T));
// No need to free stack memory
}
const handler_type* get_handler() const {
return handler;
} // data: protected:
struct handler_type {
unsigned char* stack;
size_t allocated_size;
size_t max_size;
size_t reference_count;
handler_type()
: stack (NULL),
allocated_size (0),
max_size (0),
reference_count (1)
{
trace_macro ("stack_allocator::mem_info cstor NULL");
}
handler_type (unsigned char* stack1, size_t size1)
: stack (stack1),
allocated_size (0),
max_size (size1),
reference_count (1)
{
trace_macro ("stack_allocator::mem_info cstori: size="<<max_size);
}
~handler_type()
{
trace_macro ("stack_allocator::mem_info dstor: size="<<max_size);
}
};
handler_type* handler;
template <typename U> friend class stack_allocator; }; // Comparison template <typename T1> bool operator==( const stack_allocator<T1>& lhs, const stack_allocator<T1>& rhs) throw() {
return lhs.get_handler() == rhs.get_handler(); } template <typename T1> bool operator!=( const stack_allocator<T1>& lhs, const stack_allocator<T1>& rhs) throw() {
return lhs.get_handler() != rhs.get_handler(); }

COPYRIGHT

Copyright (C) 2000-2018 Pierre Saramito <Pierre.Saramito@imag.fr> GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>. This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law.

rheolef-7.0 rheolef-7.0