| 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 |