Memory.h
Go to the documentation of this file.
1 //=================================================================================================
33 //=================================================================================================
34 
35 #ifndef _BLAZE_UTIL_MEMORY_H_
36 #define _BLAZE_UTIL_MEMORY_H_
37 
38 
39 //*************************************************************************************************
40 // Includes
41 //*************************************************************************************************
42 
43 #if defined(_MSC_VER) || defined(__MINGW64_VERSION_MAJOR) || defined(__MINGW32__)
44 # include <malloc.h>
45 #endif
46 #include <cstdlib>
47 #include <new>
48 #include <blaze/util/Assert.h>
49 #include <blaze/util/DisableIf.h>
50 #include <blaze/util/EnableIf.h>
51 #include <blaze/util/Exception.h>
52 #include <blaze/util/Types.h>
55 
56 
57 namespace blaze {
58 
59 //=================================================================================================
60 //
61 // BACKEND ALLOCATION FUNCTIONS
62 //
63 //=================================================================================================
64 
65 //*************************************************************************************************
79 inline byte_t* allocate_backend( size_t size, size_t alignment )
80 {
81  void* raw( nullptr );
82 
83 #if defined(_MSC_VER) || defined(__MINGW64_VERSION_MAJOR)
84  raw = _aligned_malloc( size, alignment );
85  if( raw == nullptr ) {
86 #elif defined(__MINGW32__)
87  raw = __mingw_aligned_malloc( size, alignment );
88  if( raw == nullptr ) {
89 #else
90  if( posix_memalign( &raw, alignment, size ) ) {
91 #endif
93  }
94 
95  return reinterpret_cast<byte_t*>( raw );
96 }
98 //*************************************************************************************************
99 
100 
101 //*************************************************************************************************
112 inline void deallocate_backend( const void* address ) noexcept
113 {
114 #if defined(_MSC_VER) || defined(__MINGW64_VERSION_MAJOR)
115  _aligned_free( const_cast<void*>( address ) );
116 #elif defined(__MINGW32__)
117  __mingw_aligned_free( const_cast<void*>( address ) );
118 #else
119  free( const_cast<void*>( address ) );
120 #endif
121 }
123 //*************************************************************************************************
124 
125 
126 
127 
128 //=================================================================================================
129 //
130 // ALLOCATION FUNCTIONS
131 //
132 //=================================================================================================
133 
134 //*************************************************************************************************
154 template< typename T >
155 EnableIf_< IsBuiltin<T>, T* > allocate( size_t size )
156 {
157  const size_t alignment( AlignmentOf<T>::value );
158 
159  if( alignment >= 8UL ) {
160  return reinterpret_cast<T*>( allocate_backend( size*sizeof(T), alignment ) );
161  }
162  else return ::new T[size];
163 }
164 //*************************************************************************************************
165 
166 
167 //*************************************************************************************************
183 template< typename T >
184 DisableIf_< IsBuiltin<T>, T* > allocate( size_t size )
185 {
186  const size_t alignment ( AlignmentOf<T>::value );
187  const size_t headersize( ( sizeof(size_t) < alignment ) ? ( alignment ) : ( sizeof( size_t ) ) );
188 
189  BLAZE_INTERNAL_ASSERT( headersize >= alignment , "Invalid header size detected" );
190  BLAZE_INTERNAL_ASSERT( headersize % alignment == 0UL, "Invalid header size detected" );
191 
192  if( alignment >= 8UL )
193  {
194  byte_t* const raw( allocate_backend( size*sizeof(T)+headersize, alignment ) );
195 
196  *reinterpret_cast<size_t*>( raw ) = size;
197 
198  T* const address( reinterpret_cast<T*>( raw + headersize ) );
199  size_t i( 0UL );
200 
201  try {
202  for( ; i<size; ++i )
203  ::new (address+i) T();
204  }
205  catch( ... ) {
206  while( i != 0UL )
207  address[--i].~T();
208  deallocate_backend( raw );
209  throw;
210  }
211 
212  return address;
213  }
214  else return ::new T[size];
215 }
216 //*************************************************************************************************
217 
218 
219 //*************************************************************************************************
229 template< typename T >
230 EnableIf_< IsBuiltin<T> > deallocate( T* address ) noexcept
231 {
232  if( address == nullptr )
233  return;
234 
235  const size_t alignment( AlignmentOf<T>::value );
236 
237  if( alignment >= 8UL ) {
238  deallocate_backend( address );
239  }
240  else ::delete[] address;
241 }
242 //*************************************************************************************************
243 
244 
245 //*************************************************************************************************
255 template< typename T >
257 {
258  if( address == nullptr )
259  return;
260 
261  const size_t alignment ( AlignmentOf<T>::value );
262  const size_t headersize( ( sizeof(size_t) < alignment ) ? ( alignment ) : ( sizeof( size_t ) ) );
263 
264  BLAZE_INTERNAL_ASSERT( headersize >= alignment , "Invalid header size detected" );
265  BLAZE_INTERNAL_ASSERT( headersize % alignment == 0UL, "Invalid header size detected" );
266 
267  if( alignment >= 8UL )
268  {
269  const byte_t* const raw = reinterpret_cast<byte_t*>( address ) - headersize;
270 
271  const size_t size( *reinterpret_cast<const size_t*>( raw ) );
272  for( size_t i=0UL; i<size; ++i )
273  address[i].~T();
274 
275  deallocate_backend( raw );
276  }
277  else ::delete[] address;
278 }
279 //*************************************************************************************************
280 
281 } // namespace blaze
282 
283 #endif
Header file for the AlignmentOf type trait.
Header file for basic type definitions.
unsigned char byte_t
Byte data type of the Blaze library.The byte data type is guaranteed to be an integral data type of s...
Definition: Types.h:79
BLAZE_ALWAYS_INLINE size_t size(const Vector< VT, TF > &vector) noexcept
Returns the current size/dimension of the vector.
Definition: Vector.h:265
Header file for exception macros.
typename DisableIf< Condition, T >::Type DisableIf_
Auxiliary type for the DisableIf class template.The DisableIf_ alias declaration provides a convenien...
Definition: DisableIf.h:224
#define BLAZE_THROW_BAD_ALLOC
Macro for the emission of a std::bad_alloc exception.This macro encapsulates the default way of Blaze...
Definition: Exception.h:139
EnableIf_< IsBuiltin< T >, T *> allocate(size_t size)
Aligned array allocation for built-in data types.
Definition: Memory.h:155
Header file for the DisableIf class template.
Namespace of the Blaze C++ math library.
Definition: Blaze.h:58
Header file for the EnableIf class template.
Header file for run time assertion macros.
EnableIf_< IsBuiltin< T > > deallocate(T *address) noexcept
Deallocation of memory for built-in data types.
Definition: Memory.h:230
typename EnableIf< Condition, T >::Type EnableIf_
Auxiliary alias declaration for the EnableIf class template.The EnableIf_ alias declaration provides ...
Definition: EnableIf.h:224
Header file for the IsBuiltin type trait.
#define BLAZE_INTERNAL_ASSERT(expr, msg)
Run time assertion macro for internal checks.In case of an invalid run time expression, the program execution is terminated. The BLAZE_INTERNAL_ASSERT macro can be disabled by setting the BLAZE_USER_ASSERTION flag to zero or by defining NDEBUG during the compilation.
Definition: Assert.h:101
Evaluation of the required alignment of the given data type.The AlignmentOf type trait template evalu...
Definition: AlignmentOf.h:219