00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00018
00019 #ifndef NET_INSTAWEB_UTIL_PUBLIC_ARENA_H_
00020 #define NET_INSTAWEB_UTIL_PUBLIC_ARENA_H_
00021
00022 #include <vector>
00023 #include <cstddef>
00024
00025 #include "base/logging.h"
00026 #include "net/instaweb/util/public/basictypes.h"
00027
00028 namespace net_instaweb {
00029
00033 template<typename T>
00034 class Arena {
00035 public:
00038 static const size_t kAlign = 8;
00039
00040 Arena() {
00041 InitEmpty();
00042 }
00043
00044 ~Arena() {
00045 CHECK(chunks_.empty());
00046 }
00047
00048 void* Allocate(size_t size) {
00049 size += kAlign;
00050 size = ExpandToAlign(size);
00051
00052 DCHECK(sizeof(void*) <= kAlign);
00053 DCHECK(size < Chunk::kSize);
00054
00055 if (next_alloc_ + size > chunk_end_) {
00056 AddChunk();
00057 }
00058
00059 char* base = next_alloc_;
00060
00064 char** our_last_link_field = reinterpret_cast<char**>(base);
00065 *last_link_ = base;
00066 *our_last_link_field = NULL;
00067 last_link_ = our_last_link_field;
00068
00069 next_alloc_ += size;
00070
00071 char* out = base + kAlign;
00072 DCHECK((reinterpret_cast<uintptr_t>(out) & (kAlign - 1)) == 0);
00073 return out;
00074 }
00075
00077 void DestroyObjects();
00078
00080 static size_t ExpandToAlign(size_t in) {
00081 return (in + kAlign - 1) & ~(kAlign - 1);
00082 }
00083
00084 private:
00085 struct Chunk {
00103 static const size_t kSize = 8192;
00104 char buf[kSize];
00105 };
00106
00108 void AddChunk();
00109
00111 void InitEmpty();
00112
00114 char* next_alloc_;
00115
00119 char** last_link_;
00120
00122 char* chunk_end_;
00123
00126 char* scratch_;
00127
00128 std::vector<Chunk*> chunks_;
00129 };
00130
00131 template<typename T>
00132 void Arena<T>::AddChunk() {
00133 Chunk* chunk = new Chunk();
00134 chunks_.push_back(chunk);
00135 next_alloc_ = chunk->buf;
00136 chunk_end_ = next_alloc_ + Chunk::kSize;
00137 last_link_ = &scratch_;
00138 }
00139
00140 template<typename T>
00141 void Arena<T>::DestroyObjects() {
00142 for (int i = 0; i < static_cast<int>(chunks_.size()); ++i) {
00144 char* base = chunks_[i]->buf;
00145 while (base != NULL) {
00146 reinterpret_cast<T*>(base + kAlign)->~T();
00147 base = *reinterpret_cast<char**>(base);
00148 }
00149 delete chunks_[i];
00150 }
00151 chunks_.clear();
00152 InitEmpty();
00153 }
00154
00155 template<typename T>
00156 void Arena<T>::InitEmpty() {
00161 next_alloc_ = NULL;
00162 last_link_ = NULL;
00163 chunk_end_ = NULL;
00164 }
00165
00166 }
00167
00168 #endif ///< NET_INSTAWEB_UTIL_PUBLIC_ARENA_H_