basix_doc 0.1
|
00001 00002 /****************************************************************************** 00003 * MODULE : fast_new.hpp 00004 * DESCRIPTION: Fast memory allocation and new operation 00005 * COPYRIGHT : (C) 1998-2008 Joris van der Hoeven 00006 ******************************************************************************* 00007 * This software falls under the GNU general public license and comes WITHOUT 00008 * ANY WARRANTY WHATSOEVER. See the file $TEXMACS_PATH/LICENSE for more details. 00009 * If you don't have this file, write to the Free Software Foundation, Inc., 00010 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 00011 ******************************************************************************/ 00012 00013 #ifndef __MMX_FAST_NEW_HPP 00014 #define __MMX_FAST_NEW_HPP 00015 #include <basix/basix-config.hpp> 00016 #include <string.h> 00017 #include <cassert> 00018 #include <stdlib.h> 00019 #include <cstdio> 00020 00021 #ifdef BASIX_ENABLE_THREADS 00022 #include <pthread.h> 00023 #endif 00024 00025 00026 #ifdef BASIX_OLD_GNU_COMPILER 00027 inline void* operator new (register size_t s, void* loc) { return loc; } 00028 inline void* operator new[] (register size_t s, void* loc) { return loc; } 00029 #else 00030 #include <new> 00031 #endif 00032 00033 #define MMX_ENABLE_FAST_ALLOCATORS 00034 00036 00037 /* 00038 #ifdef USE_STANDARD_NEW_DELETE 00039 // Optional check that standard new and delete are never used 00040 inline void* operator new (register size_t s) { assert (false); } 00041 inline void operator delete (register void* ptr) { assert (false); } 00042 inline void* operator new[] (register size_t s) { assert (false); } 00043 inline void operator delete[] (register void* ptr) { assert (false); } 00044 #endif 00045 */ 00046 00047 namespace mmx { 00048 00049 typedef unsigned int nat; 00050 typedef unsigned char uchar; 00051 typedef unsigned short ushort; 00052 typedef unsigned int uint; 00053 typedef unsigned long ulong; 00054 00055 #if defined (_CRAY) && ! defined (_CRAYMPP) 00056 typedef int xint; 00057 typedef nat xnat; 00058 #else 00059 typedef long int xint; 00060 typedef unsigned long int xnat; 00061 #endif 00062 00063 /****************************************************************************** 00064 * Mutexes support for threads 00065 ******************************************************************************/ 00066 00067 #ifdef BASIX_ENABLE_THREADS 00068 00069 class mutex { 00070 pthread_mutex_t rep; 00071 public: 00072 inline mutex () { pthread_mutex_init (&rep, NULL); } 00073 inline ~mutex () { pthread_mutex_destroy (&rep); } 00074 friend class mutex_lock; 00075 }; 00076 00077 class mutex_lock { 00078 pthread_mutex_t* rep; 00079 public: 00080 inline mutex_lock (mutex& m): rep (&(m.rep)) { 00081 pthread_mutex_lock (rep); } 00082 inline ~mutex_lock () { 00083 pthread_mutex_unlock (rep); } 00084 }; 00085 00086 #else 00087 00088 class mutex {}; 00089 struct mutex_lock { inline mutex_lock (mutex& m) { (void) m; } }; 00090 00091 #endif 00092 00093 extern mutex memory_lock; 00094 #ifdef BASIX_ENABLE_THREADS 00095 extern bool threads_active; 00096 #else 00097 static const bool threads_active= false; 00098 #endif 00099 00100 /****************************************************************************** 00101 * Allocators and Deallocators 00102 ******************************************************************************/ 00103 00104 #ifdef MMX_ENABLE_FAST_ALLOCATORS 00105 00106 #define MMX_WORD_LENGTH sizeof(void*) 00107 #define MMX_WORD_LENGTH_INC (sizeof(void*)-1) 00108 #define MMX_WORD_MASK (-sizeof(void*)) 00109 #define MMX_LAST_FAST 256 // should be a power of two 00110 #define MMX_MAX_FAST (MMX_LAST_FAST+MMX_WORD_LENGTH) 00111 #define MMX_BLOCK_SIZE 65504 // 32 smaller than power of 2 and >>> MAX_FAST 00112 00113 extern char alloc_table[MMX_MAX_FAST]; 00114 extern char* alloc_mem; 00115 extern size_t alloc_remains; 00116 extern nat allocated; 00117 extern nat fast_chunks; 00118 extern nat large_uses; 00119 00120 #define MMX_ALLOC_PTR(i) (*((void **) (alloc_table+i))) 00121 #define MMX_IND(ptr) (*((void **) ptr)) 00122 00123 void* safe_malloc (register size_t sz); 00124 00125 inline void 00126 safe_free (register void* ptr) { 00127 //printf ("Free : %p, %p\n", ptr, 00128 // *((void**) ((void*) (((char*) ptr) - sizeof (void*))))); 00129 free (*((void**) ((void*) (((char*) ptr) - sizeof (void*))))); 00130 } 00131 00132 void* enlarge_malloc (register size_t sz); 00133 00134 void* mmx_malloc_thread_unsafe (register size_t sz); 00135 00136 void mmx_free_thread_unsafe (register void* ptr, register size_t sz); 00137 00138 void* mmx_realloc_thread_unsafe (register void* old_ptr, 00139 register size_t old_sz, 00140 register size_t new_sz); 00141 00142 #else // not MMX_ENABLE_FAST_ALLOCATORS 00143 00144 extern size_t bytes_in_use; 00145 00146 inline void* 00147 mmx_malloc_thread_unsafe (size_t new_size) { 00148 //if (new_size > 32) 00149 // printf ("[+%u]", new_size); fflush (stdout); 00150 bytes_in_use += new_size; 00151 void* ptr= malloc (new_size); 00152 if (ptr == NULL) { 00153 fprintf (stderr, "Fatal error: out of memory\n"); 00154 exit (1); 00155 } 00156 return ptr; 00157 } 00158 00159 inline void* 00160 mmx_realloc_thread_unsafe (void* old_ptr, size_t old_size, size_t new_size) { 00161 //if (new_size > 32) 00162 // printf ("[%u->%u]", old_size, new_size); fflush (stdout); 00163 bytes_in_use += new_size - old_size; 00164 void* ptr= realloc (old_ptr, new_size); 00165 if (ptr == NULL) { 00166 fprintf (stderr, "Fatal error: out of memory\n"); 00167 exit (1); 00168 } 00169 return ptr; 00170 } 00171 00172 inline void 00173 mmx_free_thread_unsafe (void* ptr, size_t old_size) { 00174 //if (old_size > 32) 00175 // printf ("[-%u]", old_size); fflush (stdout); 00176 bytes_in_use -= old_size; 00177 free (ptr); 00178 } 00179 00180 #endif // MMX_ENABLE_FAST_ALLOCATORS 00181 00182 inline void* 00183 mmx_malloc_thread_safe (size_t new_size) { 00184 mutex_lock lock (memory_lock); 00185 return mmx_malloc_thread_unsafe (new_size); } 00186 00187 inline void* 00188 mmx_realloc_thread_safe (void* ptr, size_t old_size, size_t new_size) { 00189 mutex_lock lock (memory_lock); 00190 return mmx_realloc_thread_unsafe (ptr, old_size, new_size); } 00191 00192 inline void 00193 mmx_free_thread_safe (void* ptr, size_t old_size) { 00194 mutex_lock lock (memory_lock); 00195 mmx_free_thread_unsafe (ptr, old_size); } 00196 00197 inline void* 00198 mmx_malloc (size_t sz) { 00199 return threads_active ? mmx_malloc_thread_safe (sz) 00200 : mmx_malloc_thread_unsafe (sz); } 00201 00202 inline void* 00203 mmx_realloc (void* ptr, size_t old_size, size_t new_size) { 00204 return threads_active ? mmx_realloc_thread_safe (ptr, old_size, new_size) 00205 : mmx_realloc_thread_unsafe (ptr, old_size, new_size);} 00206 00207 inline void 00208 mmx_free (void* ptr, size_t old_size) { 00209 threads_active ? mmx_free_thread_safe (ptr, old_size) 00210 : mmx_free_thread_unsafe (ptr, old_size); } 00211 00212 #define MMX_ALLOCATORS \ 00213 public: \ 00214 inline void* operator new (size_t sz) { \ 00215 return mmx_malloc (sz); } \ 00216 inline void* operator new (size_t sz, void* where) { \ 00217 (void) sz; return where; } \ 00218 inline void* operator new[] (size_t sz) { \ 00219 return mmx_malloc (sz); } \ 00220 inline void* operator new[] (size_t sz, void* where) { \ 00221 (void) sz; return where; } \ 00222 inline void operator delete (void* ptr, size_t sz) { \ 00223 mmx_free (ptr, sz); } \ 00224 inline void operator delete[] (void* ptr, size_t sz) { \ 00225 mmx_free (ptr, sz); } 00226 00227 /****************************************************************************** 00228 * Fast array allocators 00229 ******************************************************************************/ 00230 00231 #ifdef MMX_ENABLE_FAST_ALLOCATORS 00232 00233 template<typename C> inline C* 00234 mmx_new (nat n) { 00235 #ifdef BASIX_ENABLE_VERIFY 00236 void* ptr= mmx_malloc (n * sizeof (C) + 16); 00237 *((nat*) ptr)= n; 00238 //printf ("{+%p}", ptr); fflush (stdout); 00239 ptr= (void*) (((char*) ptr) + 16); 00240 //printf ("{++%p}", ptr); fflush (stdout); 00241 #else 00242 void* ptr= mmx_malloc (n * sizeof (C)); 00243 #endif 00244 C* ctr= (C*) ptr; 00245 for (nat i=0; i<n; i++, ctr++) 00246 (void) new ((void*) ctr) C (); 00247 return (C*) ptr; 00248 } 00249 00250 template<typename C, typename T1> inline C* 00251 mmx_new (nat n, const T1& a1) { 00252 #ifdef BASIX_ENABLE_VERIFY 00253 void* ptr= mmx_malloc (n * sizeof (C) + 16); 00254 *((nat*) ptr)= n; 00255 //printf ("{.+%p}", ptr); fflush (stdout); 00256 ptr= (void*) (((char*) ptr) + 16); 00257 //printf ("{.++%p}", ptr); fflush (stdout); 00258 #else 00259 void* ptr= mmx_malloc (n * sizeof (C)); 00260 #endif 00261 C* ctr= (C*) ptr; 00262 for (nat i=0; i<n; i++, ctr++) 00263 (void) new ((void*) ctr) C (a1); 00264 return (C*) ptr; 00265 } 00266 00267 template<typename C, typename T1, typename T2> inline C* 00268 mmx_new (nat n, const T1& a1, const T2& a2) { 00269 #ifdef BASIX_ENABLE_VERIFY 00270 void* ptr= mmx_malloc (n * sizeof (C) + 16); 00271 *((nat*) ptr)= n; 00272 //printf ("{..+%p}", ptr); fflush (stdout); 00273 ptr= (void*) (((char*) ptr) + 16); 00274 //printf ("{..++%p}", ptr); fflush (stdout); 00275 #else 00276 void* ptr= mmx_malloc (n * sizeof (C)); 00277 #endif 00278 C* ctr= (C*) ptr; 00279 for (nat i=0; i<n; i++, ctr++) 00280 (void) new ((void*) ctr) C (a1, a2); 00281 return (C*) ptr; 00282 } 00283 00284 template<typename C> inline void 00285 mmx_delete (C* Ptr, nat n) { 00286 #ifdef BASIX_ENABLE_VERIFY 00287 void* ptr= (void*) Ptr; 00288 //printf ("{--%p}", ptr); fflush (stdout); 00289 ptr= (void*) (((char*) ptr) - 16); 00290 //printf ("{-%p}", ptr); fflush (stdout); 00291 if (*((nat*) ptr) != n) 00292 printf ("[%u should be %u]\n", n, *((nat*) ptr)); 00293 assert (*((nat*) ptr) == n); 00294 C* ctr= Ptr+n-1; 00295 for (nat i=0; i<n; i++, ctr--) ctr -> ~C(); 00296 mmx_free (ptr, n * sizeof (C) + 16); 00297 #else 00298 C* ctr= Ptr+n-1; 00299 for (nat i=0; i<n; i++, ctr--) ctr -> ~C(); 00300 mmx_free ((void*) Ptr, n * sizeof (C)); 00301 #endif 00302 } 00303 00304 template<typename C> inline C* 00305 mmx_new_one () { 00306 return mmx_new<C> (1); 00307 } 00308 00309 template<typename C, typename T1> inline C* 00310 mmx_new_one (const T1& a1) { 00311 return mmx_new<C> (1, a1); 00312 } 00313 00314 template<typename C> inline void 00315 mmx_delete_one (C* ptr) { 00316 mmx_delete<C> (ptr, 1); 00317 } 00318 00319 template<typename C> inline C* 00320 mmx_classical_new (nat n) { 00321 void* ptr= mmx_malloc (n * sizeof (C) + sizeof (nat)); 00322 *((nat*) ptr)= n; 00323 ptr= (void*) (((nat*) ptr) + 1); 00324 C* ctr= (C*) ptr; 00325 for (nat i=0; i<n; i++, ctr++) 00326 (void) new ((void*) ctr) C (); 00327 return (C*) ptr; 00328 } 00329 00330 template<typename C> inline void 00331 mmx_classical_delete (C* Ptr) { 00332 void* ptr= (void*) (((nat*) ((void*) Ptr)) - 1); 00333 nat n= *((nat*) ptr); 00334 C* ctr= Ptr+n-1; 00335 for (nat i=0; i<n; i++, ctr--) ctr -> ~C(); 00336 mmx_free (ptr, n * sizeof (C) + sizeof (nat)); 00337 } 00338 00339 /****************************************************************************** 00340 * Wrapper for slower default allocators 00341 ******************************************************************************/ 00342 00343 #else // not MMX_ENABLE_FAST_ALLOCATORS 00344 00345 template<typename C> inline C* 00346 mmx_new (nat n) { 00347 return new C[n]; 00348 } 00349 00350 template<typename C, typename T1> inline C* 00351 mmx_new (nat n, const T1& a1) { 00352 C* ptr= new C[n]; 00353 for (nat i=0; i<n; i++) ptr[i]= C(a1); 00354 return ptr; 00355 } 00356 00357 template<typename C> inline void 00358 mmx_delete (C* ptr, nat n) { 00359 (void) n; 00360 delete[] ptr; 00361 } 00362 00363 template<typename C> inline C* 00364 mmx_new_one () { 00365 return new C (); 00366 } 00367 00368 template<typename C, typename T1> inline C* 00369 mmx_new_one (const T1& a1) { 00370 return new C (a1);} 00371 00372 template<typename C> inline void 00373 mmx_delete_one (C* ptr) { 00374 delete ptr; 00375 } 00376 00377 template<typename C> inline C* 00378 mmx_classical_new (nat n) { 00379 return new C[n]; 00380 } 00381 00382 template<typename C> inline void 00383 mmx_classical_delete (C* ptr) { 00384 delete[] ptr; 00385 } 00386 00387 #endif // MMX_ENABLE_FAST_ALLOCATORS 00388 00389 size_t mmx_used_bytes (); 00390 00391 } // namespace mmx 00392 #endif // __MMX_FAST_NEW_HPP