Page Speed Optimization Libraries
1.2.24.1
|
00001 /* 00002 * Copyright 2011 Google Inc. 00003 * 00004 * Licensed under the Apache License, Version 2.0 (the "License"); 00005 * you may not use this file except in compliance with the License. 00006 * You may obtain a copy of the License at 00007 * 00008 * http:///www.apache.org/licenses/LICENSE-2.0 00009 * 00010 * Unless required by applicable law or agreed to in writing, software 00011 * distributed under the License is distributed on an "AS IS" BASIS, 00012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00013 * See the License for the specific language governing permissions and 00014 * limitations under the License. 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_