spot
0.8.2
|
00001 // Copyright (C) 2011 Laboratoire de Recherche et Developpement de 00002 // l'Epita (LRDE) 00003 // 00004 // This file is part of Spot, a model checking library. 00005 // 00006 // Spot is free software; you can redistribute it and/or modify it 00007 // under the terms of the GNU General Public License as published by 00008 // the Free Software Foundation; either version 2 of the License, or 00009 // (at your option) any later version. 00010 // 00011 // Spot is distributed in the hope that it will be useful, but WITHOUT 00012 // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 00013 // or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public 00014 // License for more details. 00015 // 00016 // You should have received a copy of the GNU General Public License 00017 // along with Spot; see the file COPYING. If not, write to the Free 00018 // Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 00019 // 02111-1307, USA. 00020 00021 #ifndef SPOT_MISC_MSPOOL_HH 00022 # define SPOT_MISC_MSPOOL_HH 00023 00024 #include <new> 00025 #include <cstddef> 00026 #include <cstdlib> 00027 #include <cassert> 00028 #include "misc/hash.hh" 00029 00030 namespace spot 00031 { 00032 00034 class multiple_size_pool 00035 { 00036 static const size_t alignment_ = 2 * sizeof(size_t) - 1; 00037 public: 00039 multiple_size_pool() 00040 : free_start_(0), free_end_(0), chunklist_(0) 00041 { 00042 } 00043 00045 ~multiple_size_pool() 00046 { 00047 while (chunklist_) 00048 { 00049 chunk_* prev = chunklist_->prev; 00050 free(chunklist_); 00051 chunklist_ = prev; 00052 } 00053 } 00054 00055 size_t fixsize(size_t size) const 00056 { 00057 if (size < sizeof(block_)) 00058 size = sizeof(block_); 00059 00060 return (size + alignment_ - 1) & ~(alignment_ - 1); 00061 } 00062 00064 void* 00065 allocate(size_t size) 00066 { 00067 size = fixsize(size); 00068 00069 block_*& f = freelist_[size]; 00070 // If we have free blocks available, return the first one. 00071 if (f) 00072 { 00073 block_* first = f; 00074 f = f->next; 00075 return first; 00076 } 00077 00078 // Else, create a block out of the last chunk of allocated 00079 // memory. 00080 00081 // If all the last chunk has been used, allocate one more. 00082 if (free_start_ + size > free_end_) 00083 { 00084 const size_t requested = (size > 128 ? size : 128) * 8192 - 64; 00085 chunk_* c = reinterpret_cast<chunk_*>(malloc(requested)); 00086 if (!c) 00087 throw std::bad_alloc(); 00088 c->prev = chunklist_; 00089 chunklist_ = c; 00090 00091 free_start_ = c->data_ + size; 00092 free_end_ = c->data_ + requested; 00093 } 00094 00095 void* res = free_start_; 00096 free_start_ += size; 00097 return res; 00098 } 00099 00109 void 00110 deallocate (const void* ptr, size_t size) 00111 { 00112 assert(ptr); 00113 size = fixsize(size); 00114 block_* b = reinterpret_cast<block_*>(const_cast<void*>(ptr)); 00115 block_*& f = freelist_[size]; 00116 b->next = f; 00117 f = b; 00118 } 00119 00120 private: 00121 struct block_ { block_* next; }; 00122 Sgi::hash_map<size_t, block_*> freelist_; 00123 char* free_start_; 00124 char* free_end_; 00125 // chunk = several agglomerated blocks 00126 union chunk_ { chunk_* prev; char data_[1]; }* chunklist_; 00127 }; 00128 00129 } 00130 00131 #endif // SPOT_MISC_INTVPOOL_HH