OLD | NEW |
| (Empty) |
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. | |
4 | |
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. | |
13 // | |
14 // The global operator new that can be used as follows: | |
15 // | |
16 // #include "lib/arena-inl.h" | |
17 // | |
18 // UnsafeArena arena(1000); | |
19 // Foo* foo = new (AllocateInArena, &arena) Foo; | |
20 // | |
21 | |
22 #ifndef RE2_UTIL_ARENA_H_ | |
23 #define RE2_UTIL_ARENA_H_ | |
24 | |
25 namespace re2 { | |
26 | |
27 // This class is thread-compatible. | |
28 class UnsafeArena { | |
29 public: | |
30 UnsafeArena(const size_t block_size); | |
31 virtual ~UnsafeArena(); | |
32 | |
33 void Reset(); | |
34 | |
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. | |
41 #ifdef __i386__ | |
42 static const int kDefaultAlignment = 4; | |
43 #else | |
44 static const int kDefaultAlignment = 8; | |
45 #endif | |
46 | |
47 private: | |
48 void* GetMemoryFallback(const size_t size, const int align); | |
49 | |
50 public: | |
51 void* GetMemory(const size_t size, const int align) { | |
52 if ( size > 0 && size < remaining_ && align == 1 ) { // common case | |
53 last_alloc_ = freestart_; | |
54 freestart_ += size; | |
55 remaining_ -= size; | |
56 return reinterpret_cast<void*>(last_alloc_); | |
57 } | |
58 return GetMemoryFallback(size, align); | |
59 } | |
60 | |
61 private: | |
62 struct AllocatedBlock { | |
63 char *mem; | |
64 size_t size; | |
65 }; | |
66 | |
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); | |
70 | |
71 const AllocatedBlock *IndexToBlock(int index) const; | |
72 | |
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 | |
77 size_t remaining_; | |
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_; | |
83 | |
84 void FreeBlocks(); // Frees all except first block | |
85 | |
86 DISALLOW_EVIL_CONSTRUCTORS(UnsafeArena); | |
87 }; | |
88 | |
89 // Operators for allocation on the arena | |
90 // Syntax: new (AllocateInArena, arena) MyClass; | |
91 // STL containers, etc. | |
92 enum AllocateInArenaType { AllocateInArena }; | |
93 | |
94 } // namespace re2 | |
95 | |
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)); | |
100 } | |
101 | |
102 #endif // RE2_UTIL_ARENA_H_ | |
103 | |
OLD | NEW |