#include <iostream>
#include <stdexcept>
//
// Инфраструктура для работы с аренами.
//
// Интерфейс арены памяти.
// Вводится для того, чтобы можно было использовать один new с разными
// типами арен.
class memory_arena_t
{
public :
virtual void *
alloc( size_t object_size ) = 0;
virtual bool
has_enough_space( size_t object_size ) const = 0;
};
// Реализация оператора new для работы с аренами памяти.
void *
operator new( size_t object_size, memory_arena_t & arena )
{
if( !arena.has_enough_space( object_size ) )
throw std::bad_alloc();
return arena.alloc( object_size );
}
//
// Реализации конкретных типов арен.
//
// Арена памяти на основе статического блока фиксированного размера.
template< size_t CAPACITY >
class fixed_arena_t : public memory_arena_t
{
public :
fixed_arena_t()
: pointer_( buffer_ )
{}
virtual void *
alloc( size_t object_size )
{
void * result = pointer_;
pointer_ += object_size;
return result;
}
virtual bool
has_enough_space( size_t object_size ) const
{
return ( pointer_ - buffer_ <= CAPACITY );
}
private :
char buffer_[ CAPACITY ];
char * pointer_;
};
//
// Прикладная логика.
//
//
// Данные типы предназначены для размещения внутри арены.
// У них нет деструкторов, поскольку деструкторы все равно
// не будут вызываться.
//
struct first_child_t
{
int x_;
int y_;
};
struct second_child_t
{
int a_;
int b_;
int c_;
};
struct owner_t
{
first_child_t * first_;
second_child_t * second_;
owner_t( first_child_t * first, second_child_t * second )
: first_( first )
, second_( second )
{}
};
// Вот пример использования арены.
void
do_something_inside_arena( memory_arena_t & arena )
{
first_child_t * first = new(arena) first_child_t();
second_child_t * second = new(arena) second_child_t();
owner_t * owner = new(arena) owner_t( first, second );
std::cout << "first: " << first
<< "\nsecond: " << second
<< "\nowner: " << owner
<< std::endl;
}
int
main()
{
try
{
fixed_arena_t< 1024 > arena;
do_something_inside_arena( arena );
}
catch( const std::exception & x )
{
std::cout << x.what() << std::endl;
}
}