Page Speed Optimization Libraries  1.3.25.1
net/instaweb/util/public/arena.h
Go to the documentation of this file.
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_
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines