Page Speed Optimization Libraries
1.4.26.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; 00074 DCHECK((reinterpret_cast<uintptr_t>(out) & (kAlign - 1)) == 0); 00075 return out; 00076 } 00077 00079 void DestroyObjects(); 00080 00082 static size_t ExpandToAlign(size_t in) { 00083 return (in + kAlign - 1) & ~(kAlign - 1); 00084 } 00085 00086 private: 00087 struct Chunk { 00105 static const size_t kSize = 8192; 00106 char buf[kSize]; 00107 }; 00108 00110 void AddChunk(); 00111 00113 void InitEmpty(); 00114 00116 char* next_alloc_; 00117 00121 char** last_link_; 00122 00124 char* chunk_end_; 00125 00128 char* scratch_; 00129 00130 std::vector<Chunk*> chunks_; 00131 }; 00132 00133 template<typename T> 00134 void Arena<T>::AddChunk() { 00135 Chunk* chunk = new Chunk(); 00136 chunks_.push_back(chunk); 00137 next_alloc_ = chunk->buf; 00138 chunk_end_ = next_alloc_ + Chunk::kSize; 00139 last_link_ = &scratch_; 00140 } 00141 00142 template<typename T> 00143 void Arena<T>::DestroyObjects() { 00144 for (int i = 0; i < static_cast<int>(chunks_.size()); ++i) { 00146 char* base = chunks_[i]->buf; 00147 while (base != NULL) { 00148 reinterpret_cast<T*>(base + kAlign)->~T(); 00149 base = *reinterpret_cast<char**>(base); 00150 } 00151 delete chunks_[i]; 00152 } 00153 chunks_.clear(); 00154 InitEmpty(); 00155 } 00156 00157 template<typename T> 00158 void Arena<T>::InitEmpty() { 00163 next_alloc_ = NULL; 00164 last_link_ = NULL; 00165 chunk_end_ = NULL; 00166 } 00167 00168 } 00169 00170 #endif ///< NET_INSTAWEB_UTIL_PUBLIC_ARENA_H_