00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014 #ifndef STXXL_ALIGNED_ALLOC
00015 #define STXXL_ALIGNED_ALLOC
00016
00017 #include <cstdlib>
00018 #include <cassert>
00019 #include <stxxl/bits/verbose.h>
00020 #include <stxxl/bits/common/utils.h>
00021
00022
00023 #ifndef STXXL_VERBOSE_ALIGNED_ALLOC
00024 #define STXXL_VERBOSE_ALIGNED_ALLOC STXXL_VERBOSE2
00025 #endif
00026
00027 __STXXL_BEGIN_NAMESPACE
00028
00029 template <typename must_be_int>
00030 struct aligned_alloc_settings {
00031 static bool may_use_realloc;
00032 };
00033
00034 template <typename must_be_int>
00035 bool aligned_alloc_settings<must_be_int>::may_use_realloc = true;
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048 template <size_t ALIGNMENT>
00049 inline void * aligned_alloc(size_t size, size_t meta_info_size = 0)
00050 {
00051 STXXL_VERBOSE2("stxxl::aligned_alloc<" << ALIGNMENT << ">(), size = " << size << ", meta info size = " << meta_info_size);
00052 #if !defined(STXXL_WASTE_MORE_MEMORY_FOR_IMPROVED_ACCESS_AFTER_ALLOCATED_MEMORY_CHECKS)
00053
00054
00055
00056
00057
00058 size_t alloc_size = ALIGNMENT + sizeof(char *) + meta_info_size + size;
00059 char * buffer = (char *)std::malloc(alloc_size);
00060 #else
00061
00062
00063
00064
00065
00066
00067
00068
00069 size_t alloc_size = ALIGNMENT * div_ceil(sizeof(char *) + meta_info_size, ALIGNMENT) + size;
00070 char * buffer;
00071 if (posix_memalign((void **)&buffer, ALIGNMENT, alloc_size) != 0)
00072 throw std::bad_alloc();
00073 #endif
00074 if (buffer == NULL)
00075 throw std::bad_alloc();
00076 #ifdef STXXL_ALIGNED_CALLOC
00077 memset(buffer, 0, alloc_size);
00078 #endif
00079 char * reserve_buffer = buffer + sizeof(char *) + meta_info_size;
00080 char * result = reserve_buffer + ALIGNMENT -
00081 (((unsigned long)reserve_buffer) % (ALIGNMENT)) - meta_info_size;
00082 STXXL_VERBOSE2("stxxl::aligned_alloc<" << ALIGNMENT << ">() address " << (void *)result << " lost " << (result - buffer) << " bytes");
00083 assert(long(result - buffer) >= long(sizeof(char *)));
00084
00085
00086
00087 size_t realloc_size = (result - buffer) + meta_info_size + size;
00088 if (realloc_size < alloc_size && aligned_alloc_settings<int>::may_use_realloc) {
00089 char * realloced = (char *)std::realloc(buffer, realloc_size);
00090 if (buffer != realloced) {
00091
00092
00093 STXXL_ERRMSG("stxxl::aligned_alloc: disabling realloc()");
00094 std::free(realloced);
00095 aligned_alloc_settings<int>::may_use_realloc = false;
00096 return aligned_alloc<ALIGNMENT>(size, meta_info_size);
00097 }
00098 assert(result + size <= buffer + realloc_size);
00099 }
00100
00101 *(((char **)result) - 1) = buffer;
00102 STXXL_VERBOSE2("stxxl::aligned_alloc<" << ALIGNMENT << ">(), allocated at " << (void *)buffer << " returning " << (void *)result);
00103 STXXL_VERBOSE_ALIGNED_ALLOC("stxxl::aligned_alloc<" << ALIGNMENT <<
00104 ">(size = " << size << ", meta info size = " << meta_info_size <<
00105 ") => buffer = " << (void *)buffer << ", ptr = " << (void *)result);
00106
00107 return result;
00108 }
00109
00110 template <size_t ALIGNMENT>
00111 inline void
00112 aligned_dealloc(void * ptr)
00113 {
00114 if (!ptr)
00115 return;
00116 char * buffer = *(((char **)ptr) - 1);
00117 STXXL_VERBOSE_ALIGNED_ALLOC("stxxl::aligned_dealloc<" << ALIGNMENT << ">(), ptr = " << ptr << ", buffer = " << (void *)buffer);
00118 std::free(buffer);
00119 }
00120
00121 __STXXL_END_NAMESPACE
00122
00123 #endif // !STXXL_ALIGNED_ALLOC
00124