src/corelib/global/qmalloc.cpp
changeset 3 41300fa6a67c
parent 0 1918ee327afb
child 4 3b1da2848fc7
equal deleted inserted replaced
2:56cd8111b7f7 3:41300fa6a67c
    63 void *qRealloc(void *ptr, size_t size)
    63 void *qRealloc(void *ptr, size_t size)
    64 {
    64 {
    65     return ::realloc(ptr, size);
    65     return ::realloc(ptr, size);
    66 }
    66 }
    67 
    67 
       
    68 void *qMallocAligned(size_t size, size_t alignment)
       
    69 {
       
    70     return qReallocAligned(0, size, 0, alignment);
       
    71 }
       
    72 
       
    73 void *qReallocAligned(void *oldptr, size_t newsize, size_t oldsize, size_t alignment)
       
    74 {
       
    75     // fake an aligned allocation
       
    76     Q_UNUSED(oldsize);
       
    77 
       
    78     void *actualptr = oldptr ? static_cast<void **>(oldptr)[-1] : 0;
       
    79     if (alignment <= sizeof(void*)) {
       
    80         // special, fast case
       
    81         void **newptr = static_cast<void **>(qRealloc(actualptr, newsize + sizeof(void*)));
       
    82         if (!newptr)
       
    83             return 0;
       
    84         if (newptr == actualptr) {
       
    85             // realloc succeeded without reallocating
       
    86             return oldptr;
       
    87         }
       
    88 
       
    89         *newptr = newptr;
       
    90         return newptr + 1;
       
    91     }
       
    92 
       
    93     union { void *ptr; void **pptr; quintptr n; } real, faked;
       
    94 
       
    95     // qMalloc returns pointers aligned at least at sizeof(size_t) boundaries
       
    96     // but usually more (8- or 16-byte boundaries).
       
    97     // So we overallocate by alignment-sizeof(size_t) bytes, so we're guaranteed to find a
       
    98     // somewhere within the first alignment-sizeof(size_t) that is properly aligned.
       
    99 
       
   100     // However, we need to store the actual pointer, so we need to allocate actually size +
       
   101     // alignment anyway.
       
   102 
       
   103     real.ptr = qRealloc(actualptr, newsize + alignment);
       
   104     if (!real.ptr)
       
   105         return 0;
       
   106 
       
   107     faked.n = real.n + alignment;
       
   108     faked.n &= ~(alignment - 1);
       
   109 
       
   110     // now save the value of the real pointer at faked-sizeof(void*)
       
   111     // by construction, alignment > sizeof(void*) and is a power of 2, so
       
   112     // faked-sizeof(void*) is properly aligned for a pointer
       
   113     faked.pptr[-1] = real.ptr;
       
   114 
       
   115     return faked.ptr;
       
   116 }
       
   117 
       
   118 void qFreeAligned(void *ptr)
       
   119 {
       
   120     if (!ptr)
       
   121         return;
       
   122     void **ptr2 = static_cast<void **>(ptr);
       
   123     free(ptr2[-1]);
       
   124 }
       
   125 
    68 QT_END_NAMESPACE
   126 QT_END_NAMESPACE