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_FIXPOOL_HH 00022 # define SPOT_MISC_FIXPOOL_HH 00023 00024 #include <new> 00025 #include <cstddef> 00026 #include <cstdlib> 00027 #include <cassert> 00028 00029 namespace spot 00030 { 00031 00033 class fixed_size_pool 00034 { 00035 public: 00037 fixed_size_pool(size_t size) 00038 : freelist_(0), free_start_(0), free_end_(0), chunklist_(0) 00039 { 00040 const size_t alignement = 2 * sizeof(size_t); 00041 size_ = ((size >= sizeof(block_) ? size : sizeof(block_)) 00042 + alignement - 1) & ~(alignement - 1); 00043 } 00044 00046 ~fixed_size_pool() 00047 { 00048 while (chunklist_) 00049 { 00050 chunk_* prev = chunklist_->prev; 00051 free(chunklist_); 00052 chunklist_ = prev; 00053 } 00054 } 00055 00057 void* 00058 allocate() 00059 { 00060 block_* f = freelist_; 00061 // If we have free blocks available, return the first one. 00062 if (f) 00063 { 00064 freelist_ = f->next; 00065 return f; 00066 } 00067 00068 // Else, create a block out of the last chunk of allocated 00069 // memory. 00070 00071 // If all the last chunk has been used, allocate one more. 00072 if (free_start_ + size_ > free_end_) 00073 { 00074 const size_t requested = (size_ > 128 ? size_ : 128) * 8192 - 64; 00075 chunk_* c = reinterpret_cast<chunk_*>(malloc(requested)); 00076 if (!c) 00077 throw std::bad_alloc(); 00078 c->prev = chunklist_; 00079 chunklist_ = c; 00080 00081 free_start_ = c->data_ + size_; 00082 free_end_ = c->data_ + requested; 00083 } 00084 00085 void* res = free_start_; 00086 free_start_ += size_; 00087 return res; 00088 } 00089 00096 void 00097 deallocate (const void* ptr) 00098 { 00099 assert(ptr); 00100 block_* b = reinterpret_cast<block_*>(const_cast<void*>(ptr)); 00101 b->next = freelist_; 00102 freelist_ = b; 00103 } 00104 00105 private: 00106 size_t size_; 00107 struct block_ { block_* next; }* freelist_; 00108 char* free_start_; 00109 char* free_end_; 00110 // chunk = several agglomerated blocks 00111 union chunk_ { chunk_* prev; char data_[1]; }* chunklist_; 00112 }; 00113 00114 } 00115 00116 #endif // SPOT_MISC_FIXPOOL_HH