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 |