ccmem.h

00001 /* MLPACK 0.2
00002  *
00003  * Copyright (c) 2008, 2009 Alexander Gray,
00004  *                          Garry Boyer,
00005  *                          Ryan Riegel,
00006  *                          Nikolaos Vasiloglou,
00007  *                          Dongryeol Lee,
00008  *                          Chip Mappus, 
00009  *                          Nishant Mehta,
00010  *                          Hua Ouyang,
00011  *                          Parikshit Ram,
00012  *                          Long Tran,
00013  *                          Wee Chin Wong
00014  *
00015  * Copyright (c) 2008, 2009 Georgia Institute of Technology
00016  *
00017  * This program is free software; you can redistribute it and/or
00018  * modify it under the terms of the GNU General Public License as
00019  * published by the Free Software Foundation; either version 2 of the
00020  * License, or (at your option) any later version.
00021  *
00022  * This program is distributed in the hope that it will be useful, but
00023  * WITHOUT ANY WARRANTY; without even the implied warranty of
00024  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00025  * General Public License for more details.
00026  *
00027  * You should have received a copy of the GNU General Public License
00028  * along with this program; if not, write to the Free Software
00029  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
00030  * 02110-1301, USA.
00031  */
00041 #ifndef BASE_CCMEM_H
00042 #define BASE_CCMEM_H
00043 
00044 #include "fastlib/base/common.h"
00045 #include "fastlib/base/debug.h"
00046 #include "fastlib/base/cc.h"
00047 
00048 #include <new>
00049 
00050 #define MEM__DEBUG_MEMORY(ptr) \
00051     DEBUG_ASSERT_MSG((ptr) != NULL, "out of memory")
00052 
00053 namespace mem__private {
00054   const size_t BIG_BAD_BUF_SIZE = 64;
00055 
00056   extern const int32 BIG_BAD_BUF[];
00057 
00058   void PoisonBytes(char *array_cp, size_t bytes);
00059 
00060   const size_t SWAP_BUF_SIZE = 64;
00061 
00062   void SwapBytes(char *a_cp, char *b_cp, size_t bytes);
00063 };
00064 
00081 namespace mem {
00083   template<typename T>
00084   T *PoisonBytes(T *array, size_t bytes) {
00085     char *array_cp = reinterpret_cast<char *>(array);
00086     mem__private::PoisonBytes(array_cp, bytes);
00087     return array;
00088   }
00090   template<typename T>
00091   inline T *Poison(T *array, size_t elems) {
00092     return PoisonBytes(array, elems * sizeof(T));
00093   }
00095   template<typename T>
00096   inline T *Poison(T *ptr) {
00097     if (sizeof(T) <= mem__private::BIG_BAD_BUF_SIZE) {
00098       return reinterpret_cast<T *>(
00099           ::memcpy(ptr, mem__private::BIG_BAD_BUF, sizeof(T)));
00100     } else {
00101       return PoisonBytes(ptr, sizeof(T));
00102     }
00103   }
00104 
00106   template<typename T>
00107   inline T *DebugPoisonBytes(T *array, size_t bytes) {
00108     DEBUG_ONLY(PoisonBytes(array, bytes));
00109     return array;
00110   }
00112   template<typename T>
00113   inline T *DebugPoison(T *array, size_t elems) {
00114     DEBUG_ONLY(Poison(array, elems));
00115     return array;
00116   }
00118   template<typename T>
00119   inline T *DebugPoison(T *ptr) {
00120     DEBUG_ONLY(Poison(ptr));
00121     return ptr;
00122   }
00123 
00125   template<typename T>
00126   inline T *AllocBytes(size_t bytes) {
00127 #ifdef SCALE_NORMAL
00128     // sanity check for small-scale problems
00129     DEBUG_BOUNDS(bytes, BIG_BAD_NUMBER);
00130 #endif
00131     T *array = reinterpret_cast<T *>(::malloc(bytes));
00132     MEM__DEBUG_MEMORY(array);
00133     return DebugPoisonBytes(array, bytes);
00134   }
00136   template<typename T>
00137   inline T *Alloc(size_t elems) {
00138 #ifdef SCALE_NORMAL
00139     // sanity check for small-scale problems
00140     DEBUG_BOUNDS(elems, BIG_BAD_NUMBER);
00141 #endif
00142     return AllocBytes<T>(elems * sizeof(T));
00143   }
00145   template<typename T>
00146   inline T *Alloc() {
00147     T *array = reinterpret_cast<T *>(::malloc(sizeof(T)));
00148     MEM__DEBUG_MEMORY(array);
00149     return DebugPoisonBytes(array);
00150   }
00151 
00153   template<typename T>
00154   inline T *ZeroBytes(T *array, size_t bytes) {
00155     return reinterpret_cast<T *>(::memset(array, 0, bytes));
00156   }
00158   template<typename T>
00159   inline T *Zero(T *array, size_t elems = 1) {
00160     return ZeroBytes(array, elems * sizeof(T));
00161   }
00163   template<typename T>
00164   inline T *AllocZeroBytes(size_t bytes) {
00165     T *array = reinterpret_cast<T *>(::calloc(bytes, 1));
00166     MEM__DEBUG_MEMORY(array);
00167     return array;
00168   }
00170   template<typename T>
00171   inline T *AllocZero(size_t elems = 1) {
00172     T *array = reinterpret_cast<T *>(::calloc(elems, sizeof(T)));
00173     MEM__DEBUG_MEMORY(array);
00174     return array;
00175   }
00176 
00178   template<typename T, typename U>
00179   inline T *CopyBytes(T *dest, const U *src, size_t bytes) {
00180     return reinterpret_cast<T *>(::memcpy(dest, src, bytes));
00181   }
00183   template<typename V, typename T, typename U>
00184   inline T *Copy(T *dest, const U *src, size_t elems = 1) {
00185     return CopyBytes(dest, src, elems * sizeof(V));
00186   }
00187   template<typename T, typename U>
00188   inline T* /*inline*/ CopyValues(T *dest, const U *src, size_t elems=1) {
00189     for(index_t i=0; i<elems; i++) {
00190       dest[i]=T(src[i]);
00191     }
00192     return dest; 
00193   }
00194   template<typename T>
00195   inline T *Copy(T *dest, const T *src, size_t elems = 1) {
00196     return Copy<T, T, T>(dest, src, elems);
00197   }
00199   template<typename T, typename U>
00200   inline T *AllocCopyBytes(const U *src, size_t bytes) {
00201     T *array = reinterpret_cast<T *>(::malloc(bytes));
00202     MEM__DEBUG_MEMORY(array);
00203     return CopyBytes(array, src, bytes);
00204   }
00206   template<typename T, typename U>
00207   inline T *AllocCopy(const U *src, size_t elems = 1) {
00208     return AllocCopyBytes<T>(src, elems * sizeof(T));
00209   }
00210 
00211   template<typename T, typename U>
00212   inline T *AllocCopyValues(const U *src, size_t elems = 1) {
00213     //FIXME
00214     T *dest/*array*/ = reinterpret_cast<T *>(::malloc(elems*sizeof(T)));
00215     MEM__DEBUG_MEMORY(dest/*array*/);
00216     return CopyValues<T, U>(dest, src, elems);
00217   }
00218 
00219   template<typename T>
00220   inline T *AllocCopy(const T *src, size_t elems = 1) {
00221     return AllocCopy<T, T>(src, elems);
00222   }
00223 
00231   template<typename T>
00232   inline T *ReallocBytes(T *array, size_t bytes) {
00233     array = reinterpret_cast<T *>(::realloc(array, bytes));
00234     MEM__DEBUG_MEMORY(array);
00235     return array;
00236   }
00244   template<typename T>
00245   inline T *Realloc(T *array, size_t elems) {
00246     return ReallocBytes<T>(array, elems * sizeof(T));
00247   }
00248 
00250   template<typename T>
00251   inline void Free(T* ptr) {
00252     ::free(ptr);
00253   }
00254 
00255 
00256 
00267   template<typename T, typename U>
00268   void SwapBytes(T *a, U *b, size_t bytes) {
00269     char *a_cp = reinterpret_cast<char *>(a);
00270     char *b_cp = reinterpret_cast<char *>(b);
00271     mem__private::SwapBytes(a_cp, b_cp, bytes);
00272   }
00283   template<typename V, typename T, typename U>
00284   inline void Swap(T *a, U *b, size_t elems) {
00285     SwapBytes(a, b, elems * sizeof(V));
00286   }
00287   template<typename T>
00288   inline void Swap(T *a, T *b, size_t elems) {
00289     Swap<T, T, T>(a, b, elems);
00290   }
00291   template<typename V, typename T, typename U>
00292   inline void Swap(T *a, U *b) {
00293     if (sizeof(V) <= mem__private::SWAP_BUF_SIZE * 2) {
00294       char buf[sizeof(V)];
00295 
00296       ::memcpy(buf, a, sizeof(V));
00297       ::memcpy(a, b, sizeof(V));
00298       ::memcpy(b, buf, sizeof(V));
00299     } else {
00300       SwapBytes(a, b, sizeof(V));
00301     }
00302   }
00303   template<typename T>
00304   inline void Swap(T *a, T *b) {
00305     Swap<T, T, T>(a, b);
00306   }
00307 
00309   template<typename T, typename U>
00310   inline T *MoveBytes(T *dest, const U *src, size_t bytes) {
00311     return reinterpret_cast<T *>(::memmove(dest, src, bytes));
00312   }
00314   template<typename V, typename T, typename U>
00315   inline T *Move(T *dest, const U *src, size_t elems = 1) {
00316     return MoveBytes(dest, src, elems * sizeof(V));
00317   }
00318   template<typename T>
00319   inline T *Move(T *dest, const T *src, size_t elems = 1) {
00320     return Move<T, T, T>(dest, src, elems);
00321   }
00322 
00323 
00324 
00326   template<typename T>
00327   inline T *Construct(T *ptr) {
00328     new(ptr) T;
00329     return ptr;
00330   }
00332   template<typename T>
00333   inline T *Construct(T *array, size_t elems) {
00334     new(array) T[elems];
00335     return array;
00336   }
00338   template<typename T>
00339   inline T *Destruct(T *ptr) {
00340     ptr->~T();
00341     return DebugPoison(ptr);
00342   }
00344   template<typename T>
00345   inline T *Destruct(T *array, size_t elems) {
00346     for (size_t i = 0; i < elems; ++i) {
00347       array[i].~T();
00348     }
00349     return DebugPoison(array, elems);
00350   }
00352   template<typename T, typename U>
00353   inline T *CopyConstruct(T *dest, const U *src) {
00354     new(dest) T(*src);
00355     return dest;
00356   }
00358   template<typename T, typename U>
00359   inline T *CopyConstruct(T *dest, const U *src, size_t elems) {
00360     for (size_t i = 0; i < elems; ++i) {
00361       new(dest + i) T(src[i]);
00362     }
00363     return dest;
00364   }
00365 
00367 #define BASE_CCMEM__SIMPLE_CONSTRUCTORS(T, TF) \
00368   template<> \
00369   inline T *Construct< T >(T *ptr) { \
00370     return DebugPoison(ptr); \
00371   } \
00372   template<> \
00373   inline T *Construct< T >(T *array, size_t elems) { \
00374     return DebugPoison(array, elems); \
00375   } \
00376   template<> \
00377   inline T *Destruct< T >(T *ptr) { \
00378     return DebugPoison(ptr); \
00379   } \
00380   template<> \
00381   inline T *Destruct< T >(T *array, size_t elems) { \
00382     return DebugPoison(array, elems); \
00383   } \
00384   template<> \
00385   inline T *CopyConstruct< T >(T *dest, const T *src) { \
00386     return Copy(dest, src, 1); \
00387   } \
00388   template<> \
00389   inline T *CopyConstruct< T >(T *dest, const T *src, size_t elems) { \
00390     return Copy(dest, src, elems); \
00391   }
00392 
00393   FOR_ALL_PRIMITIVES_DO(BASE_CCMEM__SIMPLE_CONSTRUCTORS)
00394   BASE_CCMEM__SIMPLE_CONSTRUCTORS(bool, "%d")
00395 
00397   template<typename T>
00398   inline T **Construct(T **array, size_t elems = 1) {
00399     return DebugPoison(array, elems);
00400   }
00402   template<typename T>
00403   inline T **Destruct(T **array, size_t elems = 1) {
00404     return DebugPoison(array, elems);
00405   }
00407   template<typename T>
00408   inline T **CopyConstruct(T **dest, const T **src, size_t elems = 1) {
00409     return Copy(dest, src, elems);
00410   }
00411 
00412 #undef BASE_CCMEM__SIMPLE_CONSTRUCTORS
00413 
00415   template<typename T, typename U>
00416   inline T *RepeatConstruct(T *array, const U &init, size_t elems) {
00417     for (size_t i = 0; i < elems; ++i) {
00418       new(array + i) T(init);
00419     }
00420     return array;
00421   }
00422 
00424   template<typename T>
00425   inline T *AllocConstruct(size_t elems = 1) {
00426     return Construct(Alloc<T>(elems), elems);
00427   }
00429   template<typename T, typename U>
00430   inline T *AllocCopyConstruct(const U *src, size_t elems = 1) {
00431     return CopyConstruct(Alloc<T>(elems), src, elems);
00432   }
00433   template<typename T>
00434   inline T *AllocCopyConstruct(const T *src, size_t elems = 1) {
00435     return AllocCopyConstruct<T, T>(src, elems);
00436   }
00438   template<typename T, typename U>
00439   inline T *AllocRepeatConstruct(const U &init, size_t elems) {
00440     return RepeatConstruct(Alloc<T>(elems), init, elems);
00441   }
00442   template<typename T>
00443   inline T *AllocRepeatConstruct(const T &init, size_t elems) {
00444     return AllocRepeatConstruct<T, T>(init, elems);
00445   }
00446 
00448   template<typename T>
00449   inline void FreeDestruct(T *array, size_t elems = 1) {
00450     Free(Destruct(array, elems));
00451   }
00452 
00453 
00454 
00456   template<typename T>
00457   inline T *PtrAddBytes(T *ptr, ptrdiff_t bytes) {
00458     return reinterpret_cast<T *>(
00459         reinterpret_cast<char *>(ptr) + bytes);
00460   }
00462   template<typename T>
00463   inline const T *PtrAddBytes(const T *ptr, ptrdiff_t bytes) {
00464     return reinterpret_cast<const T *>(
00465         reinterpret_cast<const char *>(ptr) + bytes);
00466   }
00468   template<typename T, typename U>
00469   inline ptrdiff_t PtrDiffBytes(const T *lhs, const U *rhs) {
00470     return reinterpret_cast<const char *>(lhs)
00471         - reinterpret_cast<const char *>(rhs);
00472   }
00474   template<typename T>
00475   inline ptrdiff_t PtrAbsAddr(const T *ptr) {
00476     return reinterpret_cast<ptrdiff_t>(ptr);
00477   }
00479   template<typename T, typename U>
00480   inline bool PtrsEqual(const T *lhs, const U *rhs) {
00481     return reinterpret_cast<size_t>(lhs)
00482         == reinterpret_cast<size_t>(rhs);
00483   }
00484 
00486 
00488   template<typename T>
00489   T *BitZeroBytes(T *array, size_t bytes) {
00490     return ZeroBytes(array, bytes);
00491   }
00493   template<typename T>
00494   T *BitZero(T *array, size_t elems = 1) {
00495     return Zero(array, elems);
00496   }
00498   template<typename T, typename U>
00499   T *BitCopyBytes(T *dest, const U *src, size_t bytes) {
00500     return CopyBytes(dest, src, bytes);
00501   }
00503   template<typename T>
00504   T *BitCopy(T *dest, const T *src, size_t elems = 1) {
00505     return Copy(dest, src, elems);
00506   }
00508   template<typename T>
00509   void BitSwap(T *a, T *b, size_t elems = 1) {
00510     Swap(a, b, elems);
00511   }
00512 };
00513 
00514 #undef MEM__DEGUG_MEMORY
00515 
00516 #endif /* BASE_CCMEM_H */
Generated on Mon Jan 24 12:04:37 2011 for FASTlib by  doxygen 1.6.3