1
// Copyright 2000 The RE2 Authors. All Rights Reserved.
2
// Use of this source code is governed by a BSD-style
3
// license that can be found in the LICENSE file.
5
// Sometimes it is necessary to allocate a large number of small
6
// objects. Doing this the usual way (malloc, new) is slow,
7
// especially for multithreaded programs. An UnsafeArena provides a
8
// mark/release method of memory management: it asks for a large chunk
9
// from the operating system and doles it out bit by bit as required.
10
// Then you free all the memory at once by calling UnsafeArena::Reset().
11
// The "Unsafe" refers to the fact that UnsafeArena is not safe to
12
// call from multiple threads.
14
// The global operator new that can be used as follows:
16
// #include "lib/arena-inl.h"
18
// UnsafeArena arena(1000);
19
// Foo* foo = new (AllocateInArena, &arena) Foo;
22
#ifndef RE2_UTIL_ARENA_H_
23
#define RE2_UTIL_ARENA_H_
27
// This class is thread-compatible.
30
UnsafeArena(const size_t block_size);
31
virtual ~UnsafeArena();
35
// This should be the worst-case alignment for any type. This is
36
// good for IA-32, SPARC version 7 (the last one I know), and
37
// supposedly Alpha. i386 would be more time-efficient with a
38
// default alignment of 8, but ::operator new() uses alignment of 4,
39
// and an assertion will fail below after the call to MakeNewBlock()
40
// if you try to use a larger alignment.
42
static const int kDefaultAlignment = 4;
44
static const int kDefaultAlignment = 8;
48
void* GetMemoryFallback(const size_t size, const int align);
51
void* GetMemory(const size_t size, const int align) {
52
if ( size > 0 && size < remaining_ && align == 1 ) { // common case
53
last_alloc_ = freestart_;
56
return reinterpret_cast<void*>(last_alloc_);
58
return GetMemoryFallback(size, align);
62
struct AllocatedBlock {
67
// The returned AllocatedBlock* is valid until the next call to AllocNewBlock
68
// or Reset (i.e. anything that might affect overflow_blocks_).
69
AllocatedBlock *AllocNewBlock(const size_t block_size);
71
const AllocatedBlock *IndexToBlock(int index) const;
73
const size_t block_size_;
74
char* freestart_; // beginning of the free space in most recent block
75
char* freestart_when_empty_; // beginning of the free space when we're empty
76
char* last_alloc_; // used to make sure ReturnBytes() is safe
78
// STL vector isn't as efficient as it could be, so we use an array at first
79
int blocks_alloced_; // how many of the first_blocks_ have been alloced
80
AllocatedBlock first_blocks_[16]; // the length of this array is arbitrary
81
// if the first_blocks_ aren't enough, expand into overflow_blocks_.
82
vector<AllocatedBlock>* overflow_blocks_;
84
void FreeBlocks(); // Frees all except first block
86
DISALLOW_EVIL_CONSTRUCTORS(UnsafeArena);
89
// Operators for allocation on the arena
90
// Syntax: new (AllocateInArena, arena) MyClass;
91
// STL containers, etc.
92
enum AllocateInArenaType { AllocateInArena };
96
inline void* operator new(size_t size,
97
re2::AllocateInArenaType /* unused */,
98
re2::UnsafeArena *arena) {
99
return reinterpret_cast<char*>(arena->GetMemory(size, 1));
102
#endif // RE2_UTIL_ARENA_H_