00001 // -*- mode: C++; c-file-style: "stroustrup"; c-basic-offset: 4; indent-tabs-mode: nil; -*- 00002 //////////////////////////////////////////////////////////////////// 00003 // 00004 // Filename : ItemAllocator.h (base) 00005 // 00006 // This file is a part of the UPPAAL toolkit. 00007 // Copyright (c) 1995 - 2003, Uppsala University and Aalborg University. 00008 // All right reserved. 00009 // 00010 // $Id: ItemAllocator.h,v 1.8 2005/01/25 18:30:22 adavid Exp $ 00011 // 00012 /////////////////////////////////////////////////////////////////// 00013 00014 #ifndef INCLUDE_BASE_ITEMALLOCATOR_H 00015 #define INCLUDE_BASE_ITEMALLOCATOR_H 00016 00017 #include <assert.h> 00018 #include <stdlib.h> 00019 #include <cstddef> 00020 00021 namespace base 00022 { 00023 /** Simple (and fast) item allocator. 00024 * The interest of it, compared 00025 * to DataAllocator is to have a different memory area (and thus 00026 * avoid messing up with the pages) for another kind of data. This 00027 * is particularly fitted to the waiting queue vs explored states 00028 * stored. 00029 * 00030 * Working of ItemAllocator: it allocates a 00031 * continuous chunk of numberOfItems items (=pool) and 00032 * initializes the list of free items. Allocation 00033 * and deallocation just pop and push items on 00034 * this list. When the list is empty, a new pool 00035 * of items is allocated. 00036 * Template arguments: 00037 * @param ITEM: type of object to allocate 00038 * Default = 128k items 00039 * @pre ITEM size is at least 1 int. 00040 */ 00041 template<class ITEM> 00042 class ItemAllocator 00043 { 00044 public: 00045 00046 /** Default number of items. 00047 */ 00048 enum { NB_ITEMS = (1 << 17) }; 00049 00050 /** Constructor: check precondition & init to NULL 00051 * @param nbItems: number of items per pool. 00052 * @pre nbItems > 1 00053 */ 00054 ItemAllocator(size_t nbItems = NB_ITEMS) 00055 : numberOfItems(nbItems), 00056 pool(NULL), 00057 freeItem(NULL) 00058 { 00059 assert(sizeof(ITEM) >= sizeof(void*)); 00060 assert(nbItems > 1); 00061 } 00062 00063 /** Destructor = reset 00064 */ 00065 ~ItemAllocator() 00066 { 00067 reset(); 00068 } 00069 00070 /** Allocate a new item. 00071 * @return new allocated item. 00072 * @post result != NULL 00073 */ 00074 ITEM* allocate() 00075 { 00076 if (!freeItem) addPool(); 00077 AllocCell_t *cell = freeItem; 00078 freeItem = cell->next; 00079 return &cell->item; 00080 } 00081 00082 /** Deallocate an item. 00083 * @param item: item to deallocate. 00084 * @pre 00085 * - item allocated with this allocator 00086 * - item != NULL 00087 */ 00088 void deallocate(ITEM *item) 00089 { 00090 assert(item); 00091 AllocCell_t *cell = (AllocCell_t*) item; 00092 cell->next = freeItem; 00093 freeItem = cell; 00094 } 00095 00096 /** Reset the allocator: free all pools 00097 * and reset the list of free items. 00098 */ 00099 void reset() 00100 { 00101 AllocPool_t *p = pool; 00102 pool = NULL; 00103 freeItem = NULL; 00104 while(p) 00105 { 00106 AllocPool_t *next = p->next; 00107 delete [] (char*) p; 00108 p = next; 00109 } 00110 } 00111 00112 private: 00113 00114 /** Add a new pool of items. 00115 */ 00116 void addPool() 00117 { 00118 // Add new pool to list of pools 00119 AllocPool_t *newPool = (AllocPool_t*) 00120 new char[sizeof(AllocPool_t)+ 00121 sizeof(AllocCell_t[numberOfItems])]; 00122 newPool->next = pool; 00123 pool = newPool; 00124 00125 // Init beginning of the list of free items 00126 AllocCell_t *item = &newPool->items[0]; 00127 assert(!freeItem); 00128 freeItem = item; 00129 00130 // Init list of free items 00131 size_t n = numberOfItems - 1; 00132 assert(numberOfItems > 1); 00133 do { 00134 item[0].next = &item[1]; 00135 item++; 00136 } while(--n); 00137 item[0].next = NULL; // last item: no next 00138 } 00139 00140 /** UNION to manage list of 00141 * free items (next) and allocation 00142 * of items (item). 00143 * Guarantee at compile time that 00144 * ITEM does not have a constructor. 00145 */ 00146 union AllocCell_t 00147 { 00148 AllocCell_t *next; 00149 ITEM item; 00150 }; 00151 00152 /** Pool of items. 00153 */ 00154 struct AllocPool_t 00155 { 00156 AllocPool_t *next; 00157 AllocCell_t items[]; 00158 }; 00159 00160 size_t numberOfItems; /**< number of items per pool */ 00161 AllocPool_t *pool; /**< allocated pools */ 00162 AllocCell_t *freeItem; /**< list of free items */ 00163 }; 00164 00165 } // namespace base 00166 00167 #endif // INCLUDE_BASE_ITEMALLOCATOR_H