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_