FXMemoryPool.h

Go to the documentation of this file.
00001 /********************************************************************************
00002 *                                                                               *
00003 *                              Custom Memory Pool                               *
00004 *                                                                               *
00005 *********************************************************************************
00006 *        Copyright (C) 2003-2009 by Niall Douglas.   All Rights Reserved.       *
00007 *       NOTE THAT I DO NOT PERMIT ANY OF MY CODE TO BE PROMOTED TO THE GPL      *
00008 *********************************************************************************
00009 * This code is free software; you can redistribute it and/or modify it under    *
00010 * the terms of the GNU Library General Public License v2.1 as published by the  *
00011 * Free Software Foundation EXCEPT that clause 3 does not apply ie; you may not  *
00012 * "upgrade" this code to the GPL without my prior written permission.           *
00013 * Please consult the file "License_Addendum2.txt" accompanying this file.       *
00014 *                                                                               *
00015 * This code is distributed in the hope that it will be useful,                  *
00016 * but WITHOUT ANY WARRANTY; without even the implied warranty of                *
00017 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.                          *
00018 *********************************************************************************
00019 * $Id:                                                                          *
00020 ********************************************************************************/
00021 
00022 #if !defined(FXDEFS_H) && !defined(DOXYGEN_SHOULD_SKIP_THIS)
00023 #include "fxdefs.h"
00024 #else
00025 
00026 #ifndef FXMEMORYPOOL_H
00027 #define FXMEMORYPOOL_H
00028 
00033 #ifdef _MSC_VER
00034 // This is a totally braindead warning :(
00035 #pragma warning(disable: 4290) // C++ exception specification ignored except it's not nothrow
00036 #endif
00037 
00038 #include <string.h>
00039 #include <new>
00040 
00041 
00069 namespace FX {
00070 
00071 class FXMemoryPool;
00072 class QThread;
00073 
00076 extern FXAPI FXMALLOCATTR void *malloc(size_t size, FXMemoryPool *heap=0, FXuint alignment=0) throw();
00079 extern FXAPI FXMALLOCATTR void *calloc(size_t no, size_t size, FXMemoryPool *heap=0, FXuint alignment=0) throw();
00082 extern FXAPI FXMALLOCATTR void *realloc(void *p, size_t size, FXMemoryPool *heap=0) throw();
00085 extern FXAPI void free(void *p, FXMemoryPool *heap=0) throw();
00086 
00089 template<typename T> inline FXMALLOCATTR T *malloc(size_t size, FXMemoryPool *heap=0, FXuint alignment=0) throw();
00090 template<typename T> inline T *malloc(size_t size, FXMemoryPool *heap, FXuint alignment) throw() { return (T *) FX::malloc(size, heap, alignment); }
00093 template<typename T> inline FXMALLOCATTR T *calloc(size_t no, size_t size, FXMemoryPool *heap=0, FXuint alignment=0) throw();
00094 template<typename T> inline T *calloc(size_t no, size_t size, FXMemoryPool *heap, FXuint alignment) throw() { return (T *) FX::calloc(no, size, heap, alignment); }
00097 template<typename T> inline FXMALLOCATTR T *realloc(T *p, size_t size, FXMemoryPool *heap=0) throw();
00098 template<typename T> inline T *realloc(T *p, size_t size, FXMemoryPool *heap) throw() { return (T *) FX::realloc((void *) p, size, heap); }
00101 template<typename T> inline void free(T *p, FXMemoryPool *heap=0) throw() { FX::free((void *) p, heap); }
00102 #if defined(DEBUG)
00103 extern FXAPI FXMALLOCATTR void *malloc_dbg(const char *file, const char *function, int lineno, size_t size, FXMemoryPool *heap=0, FXuint alignment=0) throw();
00104 extern FXAPI FXMALLOCATTR void *calloc_dbg(const char *file, const char *function, int lineno, size_t no, size_t size, FXMemoryPool *heap=0, FXuint alignment=0) throw();
00105 extern FXAPI FXMALLOCATTR void *realloc_dbg(const char *file, const char *function, int lineno, void *p, size_t size, FXMemoryPool *heap=0) throw();
00106 
00107 template<typename T> inline FXMALLOCATTR T *malloc_dbg(const char *file, const char *function, int lineno, size_t size, FXMemoryPool *heap=0, FXuint alignment=0) throw();
00108 template<typename T> inline T *malloc_dbg(const char *file, const char *function, int lineno, size_t size, FXMemoryPool *heap, FXuint alignment) throw() { return (T *) malloc_dbg(file, function, lineno, size, heap, alignment); };
00109 template<typename T> inline FXMALLOCATTR void *calloc_dbg(const char *file, const char *function, int lineno, size_t no, size_t size, FXMemoryPool *heap=0, FXuint alignment=0) throw();
00110 template<typename T> inline T *calloc_dbg(const char *file, const char *function, int lineno, size_t no, size_t size, FXMemoryPool *heap, FXuint alignment) throw() { return (T *) calloc_dbg(file, function, lineno, no, size, heap, alignment); };
00111 template<typename T> inline FXMALLOCATTR T *realloc_dbg(const char *file, const char *function, int lineno, T *ptr, size_t size, FXMemoryPool *heap=0) throw();
00112 template<typename T> inline T *realloc_dbg(const char *file, const char *function, int lineno, T *ptr, size_t size, FXMemoryPool *heap) throw() { return (T *) realloc_dbg(file, function, lineno, (void *) ptr, size, heap); };
00113 }
00114 // Just to keep non FX namespace users happy
00115 inline FXMALLOCATTR void *malloc_dbg(const char *file, const char *function, int lineno, size_t size) throw() { return malloc(size); }
00116 inline FXMALLOCATTR void *calloc_dbg(const char *file, const char *function, int lineno, size_t no, size_t size) throw() { return calloc(no, size); }
00117 inline FXMALLOCATTR void *realloc_dbg(const char *file, const char *function, int lineno, void *ptr, size_t size) throw() { return realloc(ptr, size); }
00118 namespace FX {
00119 extern FXAPI bool printLeakedBlocks() throw();
00120 #endif
00121 // This one caught me out for a while
00124 inline FXMALLOCATTR char *strdup(const char *str) throw();
00125 inline char *strdup(const char *str) throw()
00126 {
00127     size_t len=strlen(str);
00128     void *ret=FX::malloc(len+1);
00129     if(!ret) return NULL;
00130     memcpy(ret, str, len+1);
00131     return (char *) ret;
00132 }
00135 extern FXAPI void failonfree(void *p, FXMemoryPool *heap=0) throw();
00138 extern FXAPI void unfailonfree(void *p, FXMemoryPool *heap=0) throw();
00139 
00147 template<typename T, int alignment> class aligned_allocator
00148 {
00149 public:
00150     typedef T *pointer;
00151     typedef const T *const_pointer;
00152     typedef T &reference;
00153     typedef const T &const_reference;
00154     typedef T value_type;
00155     typedef size_t size_type;
00156     typedef ptrdiff_t difference_type;
00157     T *address(T &r) const { return &r; }
00158     const T *address(const T &s) const { return &s; }
00159     size_t max_size() const { return (static_cast<size_t>(0) - static_cast<size_t>(1)) / sizeof(T); }
00160     template <typename U> struct rebind {
00161         typedef aligned_allocator<U, alignment> other;
00162     };
00163     bool operator!=(const aligned_allocator &other) const { return !(*this == other); }
00164     bool operator==(const aligned_allocator &other) const { return true; }
00165 
00166     void construct(T *const p, const T &t) const {
00167         void * const pv = static_cast<void *>(p);
00168         new (pv) T(t);
00169     }
00170     void destroy(T *const p) const {
00171         p->~T();
00172     }
00173     aligned_allocator() { }
00174     aligned_allocator(const aligned_allocator &) { }
00175     template <typename U> aligned_allocator(const aligned_allocator<U, alignment> &) { }
00176 
00177     T *allocate(const size_t n) const {
00178         void *pv = malloc(n * sizeof(T), 0, alignment);
00179         if (pv == NULL) throw std::bad_alloc();
00180         return static_cast<T *>(pv);
00181     }
00182     void deallocate(T *p, const size_t n) const {
00183         free(p, 0);
00184     }
00185     template <typename U> T * allocate(const size_t n, const U * /* const hint */) const {
00186         return allocate(n);
00187     }
00188 private:
00189     aligned_allocator &operator=(const aligned_allocator &);
00190 };
00191 
00192 
00193 } // namespace
00194 
00197 inline FXDLLPUBLIC FXMALLOCATTR void *operator new(size_t size, FX::FXMemoryPool *heap, FX::FXuint alignment=0) throw(std::bad_alloc);
00198 inline FXDLLPUBLIC void *operator new(size_t size, FX::FXMemoryPool *heap, FX::FXuint alignment) throw(std::bad_alloc)
00199 {
00200     void *ret;
00201     if(!(ret=FX::malloc(size, heap, alignment))) throw std::bad_alloc();
00202     return ret;
00203 }
00206 inline FXDLLPUBLIC FXMALLOCATTR void *operator new[](size_t size, FX::FXMemoryPool *heap, FX::FXuint alignment=0) throw(std::bad_alloc);
00207 inline FXDLLPUBLIC void *operator new[](size_t size, FX::FXMemoryPool *heap, FX::FXuint alignment) throw(std::bad_alloc)
00208 {
00209     void *ret;
00210     if(!(ret=FX::malloc(size, heap, alignment))) throw std::bad_alloc();
00211     return ret;
00212 }
00215 inline FXDLLPUBLIC void operator delete(void *p, FX::FXMemoryPool *heap) throw()
00216 {
00217     if(p) FX::free(p, heap);
00218 }
00221 inline FXDLLPUBLIC void operator delete[](void *p, FX::FXMemoryPool *heap) throw()
00222 {
00223     if(p) FX::free(p, heap);
00224 }
00225 #ifdef DEBUG
00226 inline FXDLLPUBLIC FXMALLOCATTR void *operator new(size_t size, const char *file, const char *function, int lineno, FX::FXMemoryPool *heap, FX::FXuint alignment) throw(std::bad_alloc);
00227 inline FXDLLPUBLIC void *operator new(size_t size, const char *file, const char *function, int lineno, FX::FXMemoryPool *heap, FX::FXuint alignment) throw(std::bad_alloc)
00228 {
00229     void *ret;
00230     if(!(ret=FX::malloc_dbg(file, function, lineno, size, heap, alignment))) throw std::bad_alloc();
00231     return ret;
00232 }
00233 inline FXDLLPUBLIC FXMALLOCATTR void *operator new[](size_t size, const char *file, const char *function, int lineno, FX::FXMemoryPool *heap, FX::FXuint alignment) throw(std::bad_alloc);
00234 inline FXDLLPUBLIC void *operator new[](size_t size, const char *file, const char *function, int lineno, FX::FXMemoryPool *heap, FX::FXuint alignment) throw(std::bad_alloc)
00235 {
00236     void *ret;
00237     if(!(ret=FX::malloc_dbg(file, function, lineno, size, heap, alignment))) throw std::bad_alloc();
00238     return ret;
00239 }
00240 inline FXDLLPUBLIC void operator delete(void *ptr, const char *file, const char *function, int lineno, FX::FXMemoryPool *heap, FX::FXuint alignment) throw()
00241 {
00242     if(ptr) FX::free(ptr, heap);
00243 }
00244 inline FXDLLPUBLIC void operator delete[](void *ptr, const char *file, const char *function, int lineno, FX::FXMemoryPool *heap, FX::FXuint alignment) throw()
00245 {
00246     if(ptr) FX::free(ptr, heap);
00247 }
00248 #endif
00249 
00250 namespace FX {
00251 
00252 
00335 struct FXMemoryPoolPrivate;
00336 class FXAPI FXMemoryPool
00337 {
00338     friend FXAPI void *malloc(size_t size, FXMemoryPool *heap, FXuint alignment) throw();
00339     friend FXAPI void *malloc_dbg(const char *file, const char *function, int lineno, size_t size, FXMemoryPool *heap, FXuint alignment) throw();
00340     friend FXAPI void *calloc(size_t no, size_t _size, FXMemoryPool *heap, FXuint alignment) throw();
00341     friend FXAPI void *calloc_dbg(const char *file, const char *function, int lineno, size_t no, size_t _size, FXMemoryPool *heap, FXuint alignment) throw();
00342     friend FXAPI void *realloc(void *p, size_t size, FXMemoryPool *heap) throw();
00343     friend FXAPI void *realloc_dbg(const char *file, const char *function, int lineno, void *p, size_t size, FXMemoryPool *heap) throw();
00344     friend FXAPI void free(void *p, FXMemoryPool *heap) throw();
00345     FXMemoryPoolPrivate *p;
00346     FXMemoryPool(const FXMemoryPool &);
00347     FXMemoryPool &operator=(const FXMemoryPool &);
00348 public:
00350     static const FXuval minHeapVirtualSpace=1024*1024;
00352     struct Statistics
00353     {
00354         FXuval arena;       
00355         FXuval freeChunks;  
00356         FXuval fastChunks;  
00357         FXuval mmapRegions; 
00358         FXuval mmapBytes;   
00359         FXuval maxAlloc;    
00360         FXuval totalFast;   
00361         FXuval totalAlloc;  
00362         FXuval totalFree;   
00363         FXuval keepCost;    
00364         Statistics(FXuval a, FXuval b, FXuval c, FXuval d, FXuval e, FXuval f,
00365             FXuval g, FXuval h, FXuval i, FXuval j) : arena(a), freeChunks(b), fastChunks(c),
00366             mmapRegions(d), mmapBytes(e), maxAlloc(f), totalFast(g), totalAlloc(h),
00367             totalFree(i), keepCost(j) { }
00368     };
00375     FXMemoryPool(FXuval maximum=(FXuval)-1, const char *identifier=0, QThread *owner=0, bool lazydeleted=false);
00376     ~FXMemoryPool();
00378     FXuval size() const throw();
00380     FXuval maxsize() const throw();
00382     FXMALLOCATTR void *malloc(FXuval size, FXuint alignment=0) throw();
00384     FXMALLOCATTR void *calloc(FXuint no, FXuval size, FXuint alignment=0) throw();
00386     void free(void *blk, FXuint alignment=0) throw();
00390     FXMALLOCATTR void *realloc(void *blk, FXuval size) throw();
00392     static FXMemoryPool *poolFromBlk(void *blk) throw();
00393 public:
00395     static FXMALLOCATTR void *glmalloc(FXuval size, FXuint alignment=0) throw();
00398     static FXMALLOCATTR void *glcalloc(FXuval no, FXuval size, FXuint alignment=0) throw();
00400     static void glfree(void *blk, FXuint alignment=0) throw();
00404     static FXMALLOCATTR void *glrealloc(void *blk, FXuval size) throw();
00406     static bool gltrim(FXuval left) throw();
00408     static Statistics glstats() throw();
00410     static FXString glstatsAsString();
00411 public:
00413     static FXMemoryPool *current();
00415     static void setCurrent(FXMemoryPool *heap);
00416 
00418     struct MemoryPoolInfo
00419     {
00420         bool deleted;           
00421         QThread *owner;     
00422         const char *identifier; 
00423         FXuval maximum;         
00424         FXuval allocated;       
00425     };
00427     static QMemArray<MemoryPoolInfo> statistics();
00428 };
00429 
00435 class FXMemPoolHold
00436 {
00437     FXMemoryPool *oldheap;
00438 public:
00439     FXMemPoolHold(FXMemoryPool *newheap) : oldheap(FXMemoryPool::current()) { FXMemoryPool::setCurrent(newheap); }
00440     ~FXMemPoolHold() { FXMemoryPool::setCurrent(oldheap); }
00441 };
00442 
00443 } // namespace
00444 
00447 extern "C" FXAPI FXMALLOCATTR void *tnfxmalloc(size_t size);
00450 extern "C" FXAPI FXMALLOCATTR void *tnfxcalloc(size_t no, size_t size);
00453 extern "C" FXAPI FXMALLOCATTR void *tnfxrealloc(void *p, size_t size);
00456 extern "C" FXAPI void tnfxfree(void *p);
00457 
00458 // Okay back in the global namespace. Define replacement new/delete but weakly
00459 // (side effect of inline) so the linker can elide all duplicates and leave one
00460 // in each binary. Ensure it's public visibility on ELF.
00463 inline FXDLLPUBLIC FXMALLOCATTR void *operator new(size_t size) throw(std::bad_alloc);
00464 inline FXDLLPUBLIC void *operator new(size_t size) throw(std::bad_alloc)
00465 {
00466     void *ret;
00467     if(!(ret=FX::malloc(size))) throw std::bad_alloc();
00468     return ret;
00469 }
00472 inline FXDLLPUBLIC FXMALLOCATTR void *operator new[](size_t size) throw(std::bad_alloc);
00473 inline FXDLLPUBLIC void *operator new[](size_t size) throw(std::bad_alloc)
00474 {
00475     void *ret;
00476     if(!(ret=FX::malloc(size))) throw std::bad_alloc();
00477     return ret;
00478 }
00481 inline FXDLLPUBLIC void operator delete(void *p) throw()
00482 {
00483     if(p) FX::free(p);
00484 }
00487 inline FXDLLPUBLIC void operator delete[](void *p) throw()
00488 {
00489     if(p) FX::free(p);
00490 }
00491 
00492 
00493 #endif
00494 #endif

(C) 2002-2009 Niall Douglas. Some parts (C) to assorted authors.
Generated on Fri Nov 20 18:31:23 2009 for TnFOX by doxygen v1.4.7