/*
* allocator.h
*
* This file is part of NEST.
*
* Copyright (C) 2004 The NEST Initiative
*
* NEST is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* NEST is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with NEST. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef ALLOCATOR_H
#define ALLOCATOR_H
#include <cassert>
#include <cstdlib>
#include <string>
namespace sli {
/**
* @addtogroup MemoryManagement Memory management
* Classes which are involved in Memory management.
*/
/**
* @defgroup PoolAllocator Pool allocator
* The pool allocator is specialized for creating many small identical objects.
* @ingroup MemoryManagement
*/
/**
* pool is a specialized allocator class for many identical small
* objects. It targets a performance close to the optimal performance
* which is achieved by allocating all needed objects at once.
* @ingroup MemoryManagement
* @ingroup PoolAllocator
*/
class pool
{
struct link { link *next; };
class chunk
{
const size_t csize;
chunk(const chunk&); //!< not implemented
chunk& operator=(const chunk&); //!< not implemented
public:
chunk *next;
char *mem;
chunk(size_t s)
:csize(s),
mem(new char[csize])
{}
~chunk()
{
delete [] mem;
mem=NULL;
}
size_t size(void)
{ return csize;}
};
size_t initial_block_size;
size_t growth_factor;
size_t block_size; //!< number of elements per chunk
size_t el_size; //!< sizeof an element
size_t instantiations; //!< number of instatiated elements
size_t total; //!< total number of allocated elements
size_t capacity; //!< number of free elements
chunk *chunks; //!< linked list of memory chunks
link *head; //!< head of free list
bool initialized_; //!< True if the pool is initialized.
void grow(size_t); //!< make pool larger by n elements
void grow(); //!< make pool larger
public:
/** Create pool for objects of size n. Initial is the inital allocation
* block size, i.e. the number of objects per block.
* growth is the factor by which the allocations block increases after
* each growth.
*/
pool();
pool(const pool &);
pool& operator=(const pool&);
pool(size_t n, size_t initial=100, size_t growth=1);
void init(size_t n, size_t initial=100, size_t growth=1);
~pool(); //!< deallocate ALL memory
/** Increase the pools capacity (free slots) to at least n.
Reserve() ensures that the pool has at least n empty slots,
i.e., that the pool can store at least n additional elements
before more memory needs to be allocated from the operating
system.
@note The semantics of pool::reserve(n) differ from the semantics
of reserve(n) for STL containers: for STL containers, n is the total
number of elements after the reserve() call, while for pool it is the
number of @b free @b elements.
@todo Adapt the semantics of capacity() and reserve() to STL semantics.
*/
void reserve(size_t n);
size_t available(void) const
{ return total-instantiations;}
inline void *alloc(void); //!< allocate one element
inline void free(void* p); //!< put element back into the pool
size_t size_of(void) const
{ return el_size;}
inline size_t get_el_size() const;
inline size_t get_instantiations() const;
inline size_t get_total() const;
};
inline
void * pool::alloc(void)
{
if(head==0)
{
grow(block_size);
block_size *= growth_factor;
}
link *p=head;
head = head->next;
++instantiations;
return p;
}
inline
void pool::free(void *elp)
{
link *p= static_cast<link *>(elp);
p->next= head;
head = p;
--instantiations;
}
inline
size_t pool::get_el_size() const
{
return el_size;
}
inline
size_t pool::get_instantiations() const
{
return instantiations;
}
inline
size_t pool::get_total() const
{
return total;
}
}
#endif