basix_doc 0.1
/Users/mourrain/Devel/mmx/basix/include/basix/fast_new.hpp
Go to the documentation of this file.
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
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines