Index: third_party/re2/util/arena.h |
diff --git a/third_party/re2/util/arena.h b/third_party/re2/util/arena.h |
new file mode 100644 |
index 0000000000000000000000000000000000000000..7eb385b00e328ce0c706fac4c901b4ebc5815ef7 |
--- /dev/null |
+++ b/third_party/re2/util/arena.h |
@@ -0,0 +1,103 @@ |
+// Copyright 2000 The RE2 Authors. All Rights Reserved. |
+// Use of this source code is governed by a BSD-style |
+// license that can be found in the LICENSE file. |
+ |
+// Sometimes it is necessary to allocate a large number of small |
+// objects. Doing this the usual way (malloc, new) is slow, |
+// especially for multithreaded programs. An UnsafeArena provides a |
+// mark/release method of memory management: it asks for a large chunk |
+// from the operating system and doles it out bit by bit as required. |
+// Then you free all the memory at once by calling UnsafeArena::Reset(). |
+// The "Unsafe" refers to the fact that UnsafeArena is not safe to |
+// call from multiple threads. |
+// |
+// The global operator new that can be used as follows: |
+// |
+// #include "lib/arena-inl.h" |
+// |
+// UnsafeArena arena(1000); |
+// Foo* foo = new (AllocateInArena, &arena) Foo; |
+// |
+ |
+#ifndef RE2_UTIL_ARENA_H_ |
+#define RE2_UTIL_ARENA_H_ |
+ |
+namespace re2 { |
+ |
+// This class is thread-compatible. |
+class UnsafeArena { |
+ public: |
+ UnsafeArena(const size_t block_size); |
+ virtual ~UnsafeArena(); |
+ |
+ void Reset(); |
+ |
+ // This should be the worst-case alignment for any type. This is |
+ // good for IA-32, SPARC version 7 (the last one I know), and |
+ // supposedly Alpha. i386 would be more time-efficient with a |
+ // default alignment of 8, but ::operator new() uses alignment of 4, |
+ // and an assertion will fail below after the call to MakeNewBlock() |
+ // if you try to use a larger alignment. |
+#ifdef __i386__ |
+ static const int kDefaultAlignment = 4; |
+#else |
+ static const int kDefaultAlignment = 8; |
+#endif |
+ |
+ private: |
+ void* GetMemoryFallback(const size_t size, const int align); |
+ |
+ public: |
+ void* GetMemory(const size_t size, const int align) { |
+ if ( size > 0 && size < remaining_ && align == 1 ) { // common case |
+ last_alloc_ = freestart_; |
+ freestart_ += size; |
+ remaining_ -= size; |
+ return reinterpret_cast<void*>(last_alloc_); |
+ } |
+ return GetMemoryFallback(size, align); |
+ } |
+ |
+ private: |
+ struct AllocatedBlock { |
+ char *mem; |
+ size_t size; |
+ }; |
+ |
+ // The returned AllocatedBlock* is valid until the next call to AllocNewBlock |
+ // or Reset (i.e. anything that might affect overflow_blocks_). |
+ AllocatedBlock *AllocNewBlock(const size_t block_size); |
+ |
+ const AllocatedBlock *IndexToBlock(int index) const; |
+ |
+ const size_t block_size_; |
+ char* freestart_; // beginning of the free space in most recent block |
+ char* freestart_when_empty_; // beginning of the free space when we're empty |
+ char* last_alloc_; // used to make sure ReturnBytes() is safe |
+ size_t remaining_; |
+ // STL vector isn't as efficient as it could be, so we use an array at first |
+ int blocks_alloced_; // how many of the first_blocks_ have been alloced |
+ AllocatedBlock first_blocks_[16]; // the length of this array is arbitrary |
+ // if the first_blocks_ aren't enough, expand into overflow_blocks_. |
+ vector<AllocatedBlock>* overflow_blocks_; |
+ |
+ void FreeBlocks(); // Frees all except first block |
+ |
+ DISALLOW_EVIL_CONSTRUCTORS(UnsafeArena); |
+}; |
+ |
+// Operators for allocation on the arena |
+// Syntax: new (AllocateInArena, arena) MyClass; |
+// STL containers, etc. |
+enum AllocateInArenaType { AllocateInArena }; |
+ |
+} // namespace re2 |
+ |
+inline void* operator new(size_t size, |
+ re2::AllocateInArenaType /* unused */, |
+ re2::UnsafeArena *arena) { |
+ return reinterpret_cast<char*>(arena->GetMemory(size, 1)); |
+} |
+ |
+#endif // RE2_UTIL_ARENA_H_ |
+ |