28 #ifndef HYPERTABLE_PAGEARENA_H
29 #define HYPERTABLE_PAGEARENA_H
40 #include <boost/noncopyable.hpp>
41 #include <boost/static_assert.hpp>
54 void *
allocate(
size_t sz) {
return std::malloc(sz); }
68 template <
typename CharT =
char,
class PageAllocatorT = DefaultPageAllocator>
87 Page(
const char *end) : next_page(0), page_end(end) {
99 return (CharT *)start;
135 if (fill + sz <=
SIZE) {
146 Page *page = (Page *) m_page_allocator.allocate(sz);
148 new (page) Page((
char *)page + sz);
151 page->next_page = m_cur_page;
152 else if (m_cur_page) {
154 page->next_page = m_cur_page->next_page;
155 m_cur_page->next_page = page;
169 m_page_limit = m_cur_page->remain();
174 return sz <= m_page_limit && m_cur_page->remain() < m_page_limit / 2;
179 Page *p =
alloc_page(sz +
sizeof(Page),
false);
190 const PageAllocatorT &
alloc = PageAllocatorT())
191 : m_cur_page(0), m_used(0), m_page_limit(0), m_page_size(
page_size),
192 m_pages(0), m_total(0), m_page_allocator(
alloc), m_gappy_limit(0) {
193 BOOST_STATIC_ASSERT(
sizeof(CharT) == 1);
223 if (m_gappy_limit >= sz) {
224 Page f((
const char*)sz);
226 typename GappyPages::iterator it = m_gappy_pages.lower_bound(&f);
228 CharT *p = page->alloc(sz);
229 m_gappy_pages.erase(it);
231 m_gappy_pages.insert(page);
233 m_gappy_limit = m_gappy_pages.size()
234 ? (*m_gappy_pages.rbegin())->remain()
240 if (
HT_LIKELY(sz <= m_cur_page->remain()))
241 return m_cur_page->alloc(sz);
245 m_gappy_pages.insert(m_cur_page);
246 m_gappy_limit = (*m_gappy_pages.rbegin())->remain();
249 return m_cur_page->alloc(sz);
255 CharT *
realloc(
void *p,
size_t oldsz,
size_t newsz) {
258 if ((
char *)p + oldsz == m_cur_page->alloc_end
259 && (
char *)p + newsz < m_cur_page->page_end) {
260 m_cur_page->alloc_end = (
char *)p + newsz;
264 memcpy(copy, p, newsz > oldsz ? oldsz : newsz);
274 CharT *
dup(
const CharT *s) {
278 size_t len = std::strlen(s) + 1;
280 memcpy(copy, s, len);
289 CharT *
dup(
const std::string& s) {
290 return dup(s.c_str(), s.length() + 1);
299 CharT *
dup(
const void *s,
size_t len) {
304 memcpy(copy, s, len);
318 m_page_allocator.deallocate(page);
320 m_page_allocator.freed(m_total);
321 m_pages = m_total = m_used = 0;
324 m_gappy_pages.clear();
345 out <<
"pages=" << m_pages <<
", total=" << m_total <<
", used=" << m_used
346 <<
"(" << m_used * 100. / m_total <<
"%)";
363 template <
typename CharT,
class PageAlloc>
365 operator<<(std::ostream& out, const PageArena<CharT, PageAlloc> &m) {
373 #endif // !HYPERTABLE_PAGEARENA_H
void deallocate(void *p)
Frees a previously allocated chunk of memory.
size_t total() const
Statistic accessors - returns total allocated size.
A memory allocator using std::malloc() and std::free().
~PageArena()
Destructor releases the whole memory and invalidates all allocated objects.
void set_page_size(size_t sz)
Sets the page size.
CharT * dup(const std::string &s)
Duplicate a std::string; memory is allocated from the pool.
CharT * dup(const void *s, size_t len)
Duplicate a buffer of size len; memory is allocated from the pool.
std::set< Page *, LtPageRemain > GappyPages
a list of pages with gaps, sorted by gap size
void swap(Self &other)
Efficiently swaps the state with another allocator.
size_t m_total
number of pages allocated
void * allocate(size_t sz)
Allocates a new chunk of memory.
std::ostream & dump_stat(std::ostream &out) const
Write allocator statistics to output stream.
bool operator()(const Page *p1, const Page *p2) const
void free()
Free the whole arena.
A structure to manage a single memory page which is used to allocate smaller memory chunks...
struct Hypertable::PageArena::TinyBuffer m_tinybuf
#define HT_EXPECT(_e_, _code_)
CharT * alloc(size_t sz)
Allocate sz bytes.
size_t m_page_limit
total number of bytes allocated by users
CharT * dup(const CharT *s)
Duplicate a null terminated string; memory is allocated from the pool.
Page * alloc_page(size_t sz, bool prepend=true)
Allocates a page of size sz.
size_t m_pages
page size in number of bytes
Logging routines and macros.
PageArena(size_t page_size=DEFAULT_PAGE_SIZE, const PageAllocatorT &alloc=PageAllocatorT())
Constructor; creates a new PageArena.
CharT * alloc_big(size_t sz)
The PageArena allocator is simple and fast, avoiding individual mallocs/frees.
size_t used() const
Statistic accessors - returns used bytes.
void freed(size_t sz)
Inform the allocator that a bulk of objects was freed by the caller.
void copy(TableDumper &, CellsBuilder &)
CharT * realloc(void *p, size_t oldsz, size_t newsz)
Realloc for newsz bytes.
bool is_normal_overflow(size_t sz)
PageArena< CharT, PageAllocatorT > Self
predicate which sorts by size
size_t page_size()
Returns the page size.
size_t pages() const
Statistic accessors - returns number of allocated pages.
size_t m_page_size
capacity in bytes of an empty page
PageAllocatorT m_page_allocator
total number of bytes occupied by pages
A small buffer (128 bytes) to satisfy very small memory allocations without allocating a page from th...
PageArena< unsigned char > ByteArena