share/Allocator.cxx

00001 // Copyright (C) 2001-2010 Vivien Mallet, INRIA
00002 // Author(s): Vivien Mallet, Marc Fragu
00003 //
00004 // This file is part of the linear-algebra library Seldon,
00005 // http://seldon.sourceforge.net/.
00006 //
00007 // Seldon is free software; you can redistribute it and/or modify it under the
00008 // terms of the GNU Lesser General Public License as published by the Free
00009 // Software Foundation; either version 2.1 of the License, or (at your option)
00010 // any later version.
00011 //
00012 // Seldon is distributed in the hope that it will be useful, but WITHOUT ANY
00013 // WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
00014 // FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
00015 // more details.
00016 //
00017 // You should have received a copy of the GNU Lesser General Public License
00018 // along with Seldon. If not, see http://www.gnu.org/licenses/.
00019 
00020 
00021 #ifndef SELDON_FILE_ALLOCATOR_CXX
00022 
00023 #include "Allocator.hxx"
00024 
00025 namespace Seldon
00026 {
00027 
00028 
00030   // MALLOCALLOC //
00032 
00033 
00034   template <class T>
00035   inline typename MallocAlloc<T>::pointer
00036   MallocAlloc<T>::allocate(int num, void* h)
00037   {
00038     return static_cast<pointer>( malloc(num * sizeof(T)) );
00039   }
00040 
00041   template <class T>
00042   inline void MallocAlloc<T>::deallocate(pointer data, int num, void* h)
00043   {
00044     free(data);
00045   }
00046 
00047   template <class T>
00048   inline void* MallocAlloc<T>::reallocate(pointer data, int num, void* h)
00049   {
00050     return realloc(reinterpret_cast<void*>(data), num * sizeof(T));
00051   }
00052 
00053   template <class T>
00054   inline void MallocAlloc<T>::memoryset(pointer data, char c, size_t num)
00055   {
00056     memset(reinterpret_cast<void*>(data), c, num);
00057   }
00058 
00059   template <class T>
00060   inline void
00061   MallocAlloc<T>::memorycpy(pointer datat, pointer datas, size_t num)
00062   {
00063     memcpy(reinterpret_cast<void*>(datat), reinterpret_cast<void*>(datas),
00064            num * sizeof(T));
00065   }
00066 
00067 
00069   // CALLOCALLOC //
00071 
00072 
00073   template <class T>
00074   inline typename CallocAlloc<T>::pointer
00075   CallocAlloc<T>::allocate(int num, void* h)
00076   {
00077     return static_cast<pointer>( calloc(num, sizeof(T)) );
00078   }
00079 
00080   template <class T>
00081   inline void CallocAlloc<T>::deallocate(pointer data, int num, void* h)
00082   {
00083     free(data);
00084   }
00085 
00086   template <class T>
00087   inline void* CallocAlloc<T>::reallocate(pointer data, int num, void* h)
00088   {
00089     return realloc(reinterpret_cast<void*>(data), num * sizeof(T));
00090   }
00091 
00092   template <class T>
00093   inline void CallocAlloc<T>::memoryset(pointer data, char c, size_t num)
00094   {
00095     memset(reinterpret_cast<void*>(data), c, num);
00096   }
00097 
00098   template <class T>
00099   inline void
00100   CallocAlloc<T>::memorycpy(pointer datat, pointer datas, size_t num)
00101   {
00102     memcpy(reinterpret_cast<void*>(datat), reinterpret_cast<void*>(datas),
00103            num * sizeof(T));
00104   }
00105 
00106 
00108   // MALLOCOBJECT //
00110 
00111 
00112   template <class T>
00113   inline typename MallocObject<T>::pointer
00114   MallocObject<T>::allocate(int num, void* h)
00115   {
00116     // The cast from char* to T* may lead to a memory shift (because of
00117     // alignment issues) under MS Windows. It requires that one allocates more
00118     // memory than necessary for memory_block.
00119 
00120     void* memory_block = malloc(sizeof(int) + sizeof(char*) +
00121                                 (num + 2) * sizeof(T));
00122     memcpy(memory_block, &num, sizeof(int));
00123     char* data = static_cast<char*>(memory_block)
00124       + sizeof(int) + sizeof(char*) + sizeof(T);
00125 
00126     // The memory shift can occur here.
00127     pointer data_P = reinterpret_cast<pointer>(new(data) T[num]);
00128 
00129     memcpy(reinterpret_cast<char *>(data_P) - sizeof(char*),
00130            &memory_block, sizeof(char*));
00131 
00132     return data_P;
00133   }
00134 
00135 
00136   template <class T>
00137   inline void MallocObject<T>::deallocate(pointer data, int num, void* h)
00138   {
00139     void * memory_block;
00140     memcpy(&memory_block,
00141            reinterpret_cast<char *>(data) - sizeof(char*), sizeof(char*));
00142     for (int i = 0; i < num; i++)
00143       data[i].~T();
00144     free(memory_block);
00145   }
00146 
00147 
00148   template <class T>
00149   inline void* MallocObject<T>::reallocate(pointer data, int num, void* h)
00150   {
00151     if (data == NULL)
00152       return allocate(num, h);
00153 
00154     void * memory_block;
00155     memcpy(&memory_block,
00156            reinterpret_cast<char *>(data) - sizeof(char*), sizeof(char*));
00157     int initial_num = *reinterpret_cast<int*>(memory_block);
00158 
00159     if (initial_num < num)
00160       {
00161         memory_block = realloc(memory_block, sizeof(int) + sizeof(char*) +
00162                                (num + 2) * sizeof(T));
00163 
00164         new(static_cast<char *>(memory_block) + sizeof(int) + sizeof(T) +
00165             sizeof(char*) + initial_num * sizeof(T)) T[num - initial_num];
00166       }
00167     else if (initial_num > num)
00168       {
00169         for (int i = num; i < initial_num; i++)
00170           data[i].~T();
00171 
00172         memory_block = realloc(memory_block, sizeof(int) + sizeof(char*) +
00173                                (num + 2) * sizeof(T));
00174 
00175       }
00176     else
00177       return data;
00178 
00179     memcpy(memory_block, &num, sizeof(int));
00180 
00181     pointer data_P =
00182       reinterpret_cast<pointer>(static_cast<char*>(memory_block) +
00183                                 sizeof(int) + sizeof(char*) + sizeof(T));
00184     memcpy(reinterpret_cast<char *>(data_P) - sizeof(char*),
00185            &memory_block, sizeof(char*));
00186 
00187     return data_P;
00188   }
00189 
00190 
00191   template <class T>
00192   inline void MallocObject<T>::memoryset(pointer data, char c, size_t num)
00193   {
00194     memset(reinterpret_cast<void*>(data), c, num);
00195   }
00196 
00197 
00198   template <class T>
00199   inline void
00200   MallocObject<T>::memorycpy(pointer datat, pointer datas, size_t num)
00201   {
00202     for (size_t i = 0; i < num; i++)
00203       datat[i] = datas[i];
00204   }
00205 
00206 
00208   // NEWALLOC //
00210 
00211 
00212   template <class T>
00213   inline typename NewAlloc<T>::pointer
00214   NewAlloc<T>::allocate(int num, void* h)
00215   {
00216     return static_cast<pointer>(new T[num]);
00217   }
00218 
00219   template <class T>
00220   inline void NewAlloc<T>::deallocate(pointer data, int num, void* h)
00221   {
00222     delete [] data;
00223   }
00224 
00225   template <class T>
00226   inline void* NewAlloc<T>::reallocate(pointer data, int num, void* h)
00227   {
00228     if (data != NULL)
00229       delete [] data;
00230     return (new T[num]);
00231   }
00232 
00233   template <class T>
00234   inline void NewAlloc<T>::memoryset(pointer data, char c, size_t num)
00235   {
00236     memset(reinterpret_cast<void*>(data), c, num);
00237   }
00238 
00239   template <class T>
00240   inline void
00241   NewAlloc<T>::memorycpy(pointer datat, pointer datas, size_t num)
00242   {
00243     for (size_t i = 0; i < num; i++)
00244       datat[i] = datas[i];
00245   }
00246 
00247 
00249   // NANALLOC //
00251 
00252 
00253   template <class T>
00254   inline typename NaNAlloc<T>::pointer
00255   NaNAlloc<T>::allocate(int num, void* h)
00256   {
00257     pointer data = static_cast<pointer>( malloc(num * sizeof(T)) );
00258     if (numeric_limits<value_type>::has_signaling_NaN)
00259       for (int i = 0; i < num; i++)
00260         data[i] = numeric_limits<value_type>::signaling_NaN();
00261     else if (numeric_limits<value_type>::has_quiet_NaN)
00262       for (int i = 0; i < num; i++)
00263         data[i] = numeric_limits<value_type>::quiet_NaN();
00264     else if  (numeric_limits<value_type>::has_infinity)
00265       for (int i = 0; i < num; i++)
00266         data[i] = numeric_limits<value_type>::infinity();
00267     return data;
00268   }
00269 
00270   template <class T>
00271   inline void NaNAlloc<T>::deallocate(pointer data, int num, void* h)
00272   {
00273     free(data);
00274   }
00275 
00276   template <class T>
00277   inline void* NaNAlloc<T>::reallocate(pointer data, int num, void* h)
00278   {
00279     void* datav = realloc(reinterpret_cast<void*>(data), num * sizeof(T));
00280     pointer datap = reinterpret_cast<pointer>(datav);
00281     if (numeric_limits<value_type>::has_signaling_NaN)
00282       for (int i = 0; i < num; i++)
00283         datap[i] = numeric_limits<value_type>::signaling_NaN();
00284     else if (numeric_limits<value_type>::has_quiet_NaN)
00285       for (int i = 0; i < num; i++)
00286         datap[i] = numeric_limits<value_type>::quiet_NaN();
00287     else if  (numeric_limits<value_type>::has_infinity)
00288       for (int i = 0; i < num; i++)
00289         datap[i] = numeric_limits<value_type>::infinity();
00290     return datav;
00291   }
00292 
00293   template <class T>
00294   inline void NaNAlloc<T>::memoryset(pointer data, char c, size_t num)
00295   {
00296     memset(reinterpret_cast<void*>(data), c, num);
00297   }
00298 
00299   template <class T>
00300   inline void
00301   NaNAlloc<T>::memorycpy(pointer datat, pointer datas, size_t num)
00302   {
00303     memcpy(reinterpret_cast<void*>(datat), reinterpret_cast<void*>(datas),
00304            num * sizeof(T));
00305   }
00306 
00307 
00308 } // namespace Seldon.
00309 
00310 #define SELDON_FILE_ALLOCATOR_CXX
00311 #endif