00001 // -*- mode: C++; c-file-style: "stroustrup"; c-basic-offset: 4; indent-tabs-mode: nil; -*- 00002 //////////////////////////////////////////////////////////////////// 00003 // 00004 // Filename : DataAllocator.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: DataAllocator.h,v 1.15 2005/04/22 15:20:10 adavid Exp $ 00011 // 00012 /////////////////////////////////////////////////////////////////// 00013 00014 #ifndef INCLUDE_BASE_DATAALLOCATOR_H 00015 #define INCLUDE_BASE_DATAALLOCATOR_H 00016 00017 #include <stdio.h> 00018 #include <iostream> 00019 #include "base/array_t.h" 00020 #include "base/c_allocator.h" 00021 #include "base/Object.h" 00022 00023 00024 /** C wrapper function for DataAllocator. 00025 * @see dbm/mingraph.h 00026 * @param size: size in int to allocate. 00027 * @param allocator: a pointer to DataAllocator 00028 */ 00029 int32_t* base_allocate(size_t size, void *allocator); 00030 00031 00032 /** C wrapper function for DataAllocator. 00033 * @see base/c_allocator.h 00034 * @param mem: memory to deallocate 00035 * @param intSize: size in int to deallocate 00036 * @param allocator: DataAllocator object 00037 * @pre memory was allocated with base_allocate and intSize corresponds 00038 * to the allocated size. 00039 */ 00040 void base_deallocate(void *mem, size_t intSize, void *allocator); 00041 00042 00043 /** C wrapper function for new. 00044 * @see dbm/mingraph.h, base/c_allocator.h 00045 * @param size: size in int to allocate. 00046 * @param unused: unused. 00047 */ 00048 int32_t* base_new(size_t size, void *unused); 00049 00050 00051 /** C wrapper function for delete. 00052 * @see base/c_allocator.h 00053 * @param mem: memory to deallocate. 00054 * @param unused1, unused2: unused parameters. 00055 */ 00056 void base_delete(void *mem, size_t unused1, void *unused2); 00057 00058 00059 /** C wrapper allocator instance for new. 00060 */ 00061 extern allocator_t base_newallocator; 00062 00063 00064 namespace base 00065 { 00066 /** Fast chunk allocator. 00067 * Has the ability to deallocate all data at once. 00068 */ 00069 class DataAllocator : public base::Object 00070 { 00071 public: 00072 DataAllocator(); 00073 ~DataAllocator(); 00074 00075 /** Allocate memory. 00076 * @param intSize: size in int units 00077 * @return a int32[intSize] allocated 00078 * memory area. 00079 * If ALIGN_WORD64 is defined then the result is aligned 00080 * on 64 bits. It is the responsability of the developper 00081 * to use the flag. It is possible to skip the flag on 00082 * Intel architecture that can cope with non aligned 00083 * addresses. 00084 * @pre intSize <= CHUNK_SIZE 00085 */ 00086 void* allocate(size_t intSize); 00087 00088 00089 /** Deallocate memory. 00090 * @pre 00091 * - memory was allocated with allocate 00092 * - size allocated was intSize 00093 * @param data: memory to deallocate 00094 * @param intSize: size in int units of the 00095 * allocated memory. 00096 */ 00097 void deallocate(void *data, size_t intSize); 00098 00099 00100 /** Reset the allocator: deallocate all 00101 * memory allocated by this allocator! 00102 */ 00103 void reset(); 00104 00105 00106 /** Print statistics, C style. 00107 * @param out: where to print. 00108 */ 00109 void printStats(FILE *out) const; 00110 00111 00112 /** Print statistics, C++ style. 00113 * @param out: where to print. 00114 * @return the ostream. 00115 */ 00116 std::ostream& printStats(std::ostream &out) const; 00117 00118 00119 /** C wrapper allocator 00120 * @return C wrapper allocator_t 00121 */ 00122 allocator_t getCAllocator() 00123 { 00124 allocator_t c_alloc = 00125 { 00126 allocData:this, 00127 allocFunction:base_allocate, 00128 deallocFunction:base_deallocate 00129 }; 00130 return c_alloc; 00131 } 00132 00133 private: 00134 /** Memory is allocated internally by 00135 * chunks. This controls the size of 00136 * these chunks. 00137 */ 00138 enum { CHUNK_SIZE = (1 << 22) }; 00139 00140 /** Table of free memory lists. 00141 * freeMem[i] starts a list of free 00142 * memory blocks of i INT size 00143 */ 00144 array_t<uintptr_t*> freeMem; 00145 00146 /** An entry in the freeMem table 00147 * at i gives a free memory block 00148 * of size i ints. If there are other 00149 * such blocks, then this memory block 00150 * contains the pointer to the next 00151 * free block. 00152 * This function is a convenience cast 00153 * for this case. 00154 */ 00155 static inline 00156 uintptr_t* getNext(uintptr_t data) 00157 { 00158 return (uintptr_t*) data; 00159 } 00160 static inline 00161 uintptr_t getNext(uintptr_t *data) 00162 { 00163 return (uintptr_t) data; 00164 } 00165 00166 00167 /** Check that a given address belongs to a pool or the free list. 00168 * Used for debugging, this is not a performance critical method. 00169 * @param data: memory to check, 00170 * @param intSize: size of the memory to check. 00171 * @return true if the memory belongs to a pool. 00172 */ 00173 bool hasInPools(const uintptr_t *data, size_t intSize) const; 00174 00175 00176 /** Memory pool. 00177 */ 00178 struct Pool_t 00179 { 00180 Pool_t *next; 00181 uintptr_t mem[CHUNK_SIZE]; 00182 uintptr_t end[]; /**< only to mark the end, no data */ 00183 }; 00184 00185 Pool_t *memPool; /**< current pool in use */ 00186 uintptr_t *freePtr; /**< current free mem position */ 00187 uintptr_t *endFree; /**< end of current chunk */ 00188 }; 00189 00190 } // namespace base 00191 00192 00193 static inline 00194 std::ostream& operator << (std::ostream& os, const base::DataAllocator& alloc) 00195 { 00196 return alloc.printStats(os); 00197 } 00198 00199 #endif // INCLUDE_ALLOCATOR_DATAALLOCATOR_H