00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
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
00039
00040
00041
00042
00043
00044
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
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
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
00128
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
00149
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
00162
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
00175
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
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
00239 ptr= (void*) (((char*) ptr) + 16);
00240
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
00256 ptr= (void*) (((char*) ptr) + 16);
00257
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
00273 ptr= (void*) (((char*) ptr) + 16);
00274
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
00289 ptr= (void*) (((char*) ptr) - 16);
00290
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
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 }
00392 #endif // __MMX_FAST_NEW_HPP