/* nedalloc, an alternative malloc implementation for multiple threads withoutlock contention based on dlmalloc v2.8.4. (C) 2005-2010 Niall DouglasBoost Software License - Version 1.0 - August 17th, 2003Permission is hereby granted, free of charge, to any person or organizationobtaining a copy of the software and accompanying documentation covered bythis license (the "Software") to use, reproduce, display, distribute,execute, and transmit the Software, and to prepare derivative works of theSoftware, and to permit third-parties to whom the Software is furnished todo so, all subject to the following:The copyright notices in the Software and this entire statement, includingthe above license grant, this restriction and the following disclaimer,must be included in all copies of the Software, in whole or in part, andall derivative works of the Software, unless such copies or derivativeworks are solely in the form of machine-executable object code generated bya source language processor.THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS ORIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENTSHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLEFOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHERDEALINGS IN THE SOFTWARE.*/#ifndef NEDMALLOC_H#define NEDMALLOC_H/*! \file nedmalloc.h\brief Defines the functionality provided by nedalloc.*//*! \mainpage<a href="../../Readme.html">Please see the Readme.html</a>*//*! \def NEDMALLOC_DEBUG\brief Defines the assertion checking performed by nedallocNEDMALLOC_DEBUG can be defined to cause DEBUG to be set differently for nedmallocthan for the rest of the build. Remember to set NDEBUG to disable all assertionchecking too.*//*! \def ENABLE_LARGE_PAGES\brief Defines whether nedalloc uses large pages (>=2Mb)ENABLE_LARGE_PAGES enables support for requesting memory from the system in large(typically >=2Mb) pages if the host OS supports this. These occupy just a singleTLB entry and can significantly improve performance in large working set applications.*//*! \def ENABLE_FAST_HEAP_DETECTION\brief Defines whether nedalloc takes platform specific shortcuts when detecting foreign blocks.ENABLE_FAST_HEAP_DETECTION enables special logic to detect blocks allocatedby the system heap. This avoids 1.5%-2% overhead when checking for non-nedmallocblocks, but it assumes that the NT and glibc heaps function in a very specificfashion which may not hold true across OS upgrades.*//*! \def HAVE_CPP0XRVALUEREFS\ingroup C++\brief Enables rvalue referencesDefine to enable the usage of rvalue references which enables move semantics andother things. Automatically defined if __cplusplus indicates a C++0x compiler,otherwise you'll need to set it yourself.*//*! \def HAVE_CPP0XVARIADICTEMPLATES\ingroup C++\brief Enables variadic templatesDefine to enable the usage of variadic templates which enables the use of arbitrarynumbers of policies and other useful things. Automatically defined if __cplusplusindicates a C++0x compiler, otherwise you'll need to set it yourself.*//*! \def HAVE_CPP0XSTATICASSERT\ingroup C++\brief Enables static assertionsDefine to enable the usage of static assertions. Automatically defined if __cplusplusindicates a C++0x compiler, otherwise you'll need to set it yourself.*//*! \def HAVE_CPP0XTYPETRAITS\ingroup C++\brief Enables type traitsDefine to enable the usage of <type_traits>. Automatically defined if __cplusplusindicates a C++0x compiler, otherwise you'll need to set it yourself.*/#if __cplusplus > 199711L || defined(HAVE_CPP0X) /* Do we have C++0x? */#undef HAVE_CPP0XRVALUEREFS#define HAVE_CPP0XRVALUEREFS 1#undef HAVE_CPP0XVARIADICTEMPLATES#define HAVE_CPP0XVARIADICTEMPLATES 1#undef HAVE_CPP0XSTATICASSERT#define HAVE_CPP0XSTATICASSERT 1#undef HAVE_CPP0XTYPETRAITS#define HAVE_CPP0XTYPETRAITS 1#endif#include <stddef.h> /* for size_t *//*! \def NEDMALLOCEXTSPEC\brief Defines how nedalloc's API is to be made visible.NEDMALLOCEXTSPEC can be defined to be __declspec(dllexport) or__attribute__ ((visibility("default"))) or whatever you like. It defaultsto extern unless NEDMALLOC_DLL_EXPORTS is set as it would be when buildingnedmalloc.dll.*/#ifndef NEDMALLOCEXTSPEC#ifdef NEDMALLOC_DLL_EXPORTS#ifdef WIN32#define NEDMALLOCEXTSPEC extern __declspec(dllexport)#elif defined(__GNUC__)#define NEDMALLOCEXTSPEC extern __attribute__ ((visibility("default")))#endif#ifndef ENABLE_TOLERANT_NEDMALLOC#define ENABLE_TOLERANT_NEDMALLOC 1#endif#else#define NEDMALLOCEXTSPEC extern#endif#endif/*! \def NEDMALLOCDEPRECATED\brief Defined to mark an API as deprecated */#ifndef NEDMALLOCDEPRECATED#if defined(_MSC_VER) && !defined(__GCCXML__)#define NEDMALLOCDEPRECATED __declspec(deprecated)#elif defined(__GNUC__) && !defined(__GCCXML__)#define NEDMALLOCDEPRECATED __attribute ((deprecated))#else//! Marks a function as being deprecated#define NEDMALLOCDEPRECATED#endif#endif/*! \def RESTRICT\brief Defined to the restrict keyword or equivalent if available */#ifndef RESTRICT#if __STDC_VERSION__ >= 199901L /* C99 or better */#define RESTRICT restrict#else#if defined(_MSC_VER) && _MSC_VER>=1400#define RESTRICT __restrict#endif#ifdef __GNUC__#define RESTRICT __restrict#endif#endif#ifndef RESTRICT#define RESTRICT#endif#endif#if defined(_MSC_VER) && _MSC_VER>=1400#define NEDMALLOCPTRATTR __declspec(restrict)#define NEDMALLOCNOALIASATTR __declspec(noalias)#endif#ifdef __GNUC__#define NEDMALLOCPTRATTR __attribute__ ((malloc))#endif/*! \def NEDMALLOCPTRATTR\brief Defined to the specifier for a pointer which points to a memory block. Like NEDMALLOCNOALIASATTR, but sadly not identical. */#ifndef NEDMALLOCPTRATTR#define NEDMALLOCPTRATTR#endif/*! \def NEDMALLOCNOALIASATTR\brief Defined to the specifier for a pointer which does not alias any other variable. */#ifndef NEDMALLOCNOALIASATTR#define NEDMALLOCNOALIASATTR#endif/*! \def USE_MAGIC_HEADERS\brief Defines whether nedalloc should use magic headers in foreign heap block detectionUSE_MAGIC_HEADERS causes nedalloc to allocate an extra three sizeof(size_t)to each block. nedpfree() and nedprealloc() can then automagically know whento free a system allocated block. Enabling this typically adds 20-50% toapplication memory usage, and is mandatory if USE_ALLOCATOR is not 1.*/#ifndef USE_MAGIC_HEADERS#define USE_MAGIC_HEADERS 0#endif/*! \def USE_ALLOCATOR\brief Defines the underlying allocator to useUSE_ALLOCATOR can be one of these settings (it defaults to 1):0: System allocator (nedmalloc now simply acts as a threadcache) which isvery useful for testing with valgrind and Glowcode.WARNING: Intended for DEBUG USE ONLY - not all functions work correctly.1: dlmalloc*/#ifndef USE_ALLOCATOR#define USE_ALLOCATOR 1 /* dlmalloc */#endif#if !USE_ALLOCATOR && !USE_MAGIC_HEADERS#error If you are using the system allocator then you MUST use magic headers#endif/*! \def REPLACE_SYSTEM_ALLOCATOR\brief Defines whether to replace the system allocator (malloc(), free() et al) with nedalloc's implementation.REPLACE_SYSTEM_ALLOCATOR on POSIX causes nedalloc's functions to be calledmalloc, free etc. instead of nedmalloc, nedfree etc. You may or may not wantthis. On Windows it causes nedmalloc to patch all loaded DLLs and binariesto replace usage of the system allocator.Always turns on ENABLE_TOLERANT_NEDMALLOC.*/#ifdef REPLACE_SYSTEM_ALLOCATOR#if USE_ALLOCATOR==0#error Cannot combine using the system allocator with replacing the system allocator#endif#ifndef ENABLE_TOLERANT_NEDMALLOC#define ENABLE_TOLERANT_NEDMALLOC 1#endif#ifndef WIN32 /* We have a dedicated patcher for Windows */#define nedmalloc malloc#define nedmalloc2 malloc2#define nedcalloc calloc#define nedrealloc realloc#define nedrealloc2 realloc2#define nedfree free#define nedfree2 free2#define nedmemalign memalign#define nedmallinfo mallinfo#define nedmallopt mallopt#define nedmalloc_trim malloc_trim#define nedmalloc_stats malloc_stats#define nedmalloc_footprint malloc_footprint#define nedindependent_calloc independent_calloc#define nedindependent_comalloc independent_comalloc#ifdef __GNUC__#define nedmemsize malloc_usable_size#endif#endif#endif/*! \def ENABLE_TOLERANT_NEDMALLOC\brief Defines whether nedalloc should check for blocks from the system allocator.ENABLE_TOLERANT_NEDMALLOC is automatically turned on if REPLACE_SYSTEM_ALLOCATORis set or the Windows DLL is being built. This causes nedmalloc to detect when asystem allocator block is passed to it and to handle it appropriately. Note thatwithout USE_MAGIC_HEADERS there is a very tiny chance that nedmalloc will segfaulton non-Windows builds (it uses Win32 SEH to trap segfaults on Windows and thereis no comparable system on POSIX).*/#if defined(__cplusplus)extern "C" {#endif/*! \brief Returns information about a memory pool */struct nedmallinfo {size_t arena; /*!< non-mmapped space allocated from system */size_t ordblks; /*!< number of free chunks */size_t smblks; /*!< always 0 */size_t hblks; /*!< always 0 */size_t hblkhd; /*!< space in mmapped regions */size_t usmblks; /*!< maximum total allocated space */size_t fsmblks; /*!< always 0 */size_t uordblks; /*!< total allocated space */size_t fordblks; /*!< total free space */size_t keepcost; /*!< releasable (via malloc_trim) space */};#if defined(__cplusplus)}#endif/*! \def NO_NED_NAMESPACE\brief Defines the use of the nedalloc namespace for the C functions.NO_NED_NAMESPACE prevents the functions from being defined in the nedallocnamespace when in C++ (uses the global C namespace instead).*//*! \def THROWSPEC\brief Defined to throw() or noexcept(true) (as in, throws nothing) under C++, otherwise nothing.*/#if defined(__cplusplus)#if !defined(NO_NED_NAMESPACE)namespace nedalloc {#elseextern "C" {#endif#if __cplusplus > 199711L#define THROWSPEC noexcept(true)#else#define THROWSPEC throw()#endif#else#define THROWSPEC#endif/* These are the global functions *//*! \defgroup v2malloc The v2 malloc API\warning This API is being completely retired in v1.10 beta 2 and replaced with the APIbeing developed for inclusion into the C1X programming language standardFor the v1.10 release which was generously sponsored by<a href="http://www.ara.com/" target="_blank">Applied Research Associates (USA)</a>,a new general purpose allocator API was designed which is intended to remedy manyof the long standing problems and inefficiencies introduced by the ISO C allocatorAPI. Internally nedalloc's implementations of nedmalloc(), nedcalloc(), nedmemalign()and nedrealloc() call into this API:<ul><li><code>void* malloc2(size_t bytes, size_t alignment, unsigned flags)</code></li><li><code>void* realloc2(void* mem, size_t bytes, size_t alignment, unsignedflags)</code></li><li><code>void free2(void* mem, unsigned flags)</code></li></ul>If nedmalloc.h is being included by C++ code, the alignment and flags parametersdefault to zero which makes the new API identical to the old API (roll on the introductionof default parameters to C!). The ability for realloc2() to take an alignment is<em>particularly</em> useful for extending aligned vector arrays such as SSE/AVXvector arrays. Hitherto SSE/AVX vector code had to jump through all sorts of unpleasanthoops to maintain alignment :(.Note that using any of these flags other than M2_ZERO_MEMORY or any alignmentother than zero inhibits the threadcache.Currently MREMAP support is limited to Linux and Windows. Patches implementingsupport for other platforms are welcome.On Linux the non portable mremap() kernel function is currently used, so in factthe M2_RESERVE_* options are currently ignored.On Windows, there are two different MREMAP implementations which are chosen accordingto whether a 32 bit or a 64 bit build is being performed. The 32 bit implementationis based on Win32 file mappings where it reserves the address space within the WindowsVM system, so you can safely specify silly reservation quantities like 2Gb per blockand not exhaust local process address space. Note however that on x86 this costs2Kb (1Kb if PAE is off) of kernel memory per Mb reserved, and as kernel memory hasa hard limit of 447Mb on x86 you will find the total address space reservable inthe system is limited. On x64, or if you define WIN32_DIRECT_USE_FILE_MAPPINGS=0on x86, a much faster implementation of using VirtualAlloc(MEM_RESERVE) to directlyreserve the address space is used.When using M2_RESERVE_* with realloc2(), the setting only takes effect when themmapped chunk has exceeded its reservation space and a new reservation space needsto be created.*/#ifndef M2_FLAGS_DEFINED#define M2_FLAGS_DEFINED/*! \def M2_ZERO_MEMORY\ingroup v2malloc\brief Sets the contents of the allocated block (or any increase in the allocatedblock) to zero.Note that this zeroes only the increase from what dlmalloc thinksthe chunk's size is, so if you realloc2() a block which wasn't allocated usingmalloc2() using this flag then you may have garbage just before the newly extendedspace.\li <strong>Rationale:</strong> Memory returned by the system is guaranteed tobe zero on most platforms, and hence dlmalloc knows when it can skip zeroingmemory. This improves performance.*/#define M2_ZERO_MEMORY (1<<0)/*! \def M2_PREVENT_MOVE\ingroup v2malloc\brief Cause realloc2() to attempt to extend a block in place, but to never moveit.\li <strong>Rationale:</strong> C++ makes almost no use of realloc(), even forcontiguous arrays such as std::vector<> because most C++ objects cannot be relocatedin memory without a copy or rvalue construction (though some clever STL implementationsspecialise for Plain Old Data (POD) types, and use realloc() then and only then).This flag allows C++ containers to speculatively try to extend in place, thusimproving performance <em>especially</em> for large allocations which will usemmap().*/#define M2_PREVENT_MOVE (1<<1)/*! \def M2_ALWAYS_MMAP\ingroup v2malloc\brief Always allocate as though mmap_threshold were being exceeded.In the case of realloc2(), note that setting this bit will not necessarily mmap a chunkwhich isn't already mmapped, but it will force a mmapped chunk if new memoryneeds allocating.\li <strong>Rationale:</strong> If you know that an array you are allocatingis going to be repeatedly extended up into the hundred of kilobytes range, thenyou can avoid the constant memory copying into larger blocks by specifying thisflag at the beginning along with one of the M2_RESERVE_* flags below. This can<strong>greatly</strong> improve performance for large arrays.*/#define M2_ALWAYS_MMAP (1<<2)#define M2_RESERVED1 (1<<3)#define M2_RESERVED2 (1<<4)#define M2_RESERVED3 (1<<5)#define M2_RESERVED4 (1<<6)#define M2_RESERVED5 (1<<7)#define M2_RESERVE_ISMULTIPLIER (1<<15)/* 7 bits is given to the address reservation specifier.This lets you set a multiplier (bit 15 set) or a 1<< shift value.*/#define M2_RESERVE_MASK 0x00007f00/*! \def M2_RESERVE_MULT(n)\ingroup v2malloc\brief Reserve n times as much address space such that mmapped realloc2(size <=n * original size) avoids memory copying and hence is much faster.*/#define M2_RESERVE_MULT(n) (M2_RESERVE_ISMULTIPLIER|(((n)<<8)&M2_RESERVE_MASK))/*! \def M2_RESERVE_SHIFT(n)\ingroup v2malloc\brief Reserve (1<<n) bytes of address space such that mmapped realloc2(size <=(1<<n)) avoids memory copying and hence is much faster.*/#define M2_RESERVE_SHIFT(n) (((n)<<8)&M2_RESERVE_MASK)#define M2_FLAGS_MASK 0x0000ffff#define M2_CUSTOM_FLAGS_BEGIN (1<<16)#define M2_CUSTOM_FLAGS_MASK 0xffff0000/*! \def NM_SKIP_TOLERANCE_CHECKS\ingroup v2malloc\brief Causes nedmalloc to not inspect the block being passed to see if it belongsto the system allocator. Can improve speed by up to 10%.*/#define NM_SKIP_TOLERANCE_CHECKS (1<<31)#endif /* M2_FLAGS_DEFINED */#if defined(__cplusplus)/*! \brief Gets the usable size of an allocated block.Note this will always be bigger than what wasasked for due to rounding etc. Optionally returns 1 in isforeign if the block came from thesystem allocator - note that there is a small (>0.01%) but real chance of segfault on non-Windowssystems when passing non-nedmalloc blocks if you don't use USE_MAGIC_HEADERS.*/NEDMALLOCEXTSPEC NEDMALLOCNOALIASATTR size_t nedblksize(int *RESTRICT isforeign, void *RESTRICT mem, unsigned flags=0) THROWSPEC;#elseNEDMALLOCEXTSPEC NEDMALLOCNOALIASATTR size_t nedblksize(int *RESTRICT isforeign, void *RESTRICT mem, unsigned flags) THROWSPEC;#endif/*! \brief Identical to nedblksize() except without the isforeign */NEDMALLOCEXTSPEC NEDMALLOCNOALIASATTR size_t nedmemsize(void *RESTRICT mem) THROWSPEC;/*! \brief Equivalent to nedpsetvalue((nedpool *) 0, v) */NEDMALLOCEXTSPEC NEDMALLOCNOALIASATTR void nedsetvalue(void *v) THROWSPEC;/*! \brief Equivalent to nedpmalloc2((nedpool *) 0, size, 0, 0) */NEDMALLOCEXTSPEC NEDMALLOCNOALIASATTR NEDMALLOCPTRATTR void * nedmalloc(size_t size) THROWSPEC;/*! \brief Equivalent to nedpmalloc2((nedpool *) 0, no*size, 0, M2_ZERO_MEMORY) */NEDMALLOCEXTSPEC NEDMALLOCNOALIASATTR NEDMALLOCPTRATTR void * nedcalloc(size_t no, size_t size) THROWSPEC;/*! \brief Equivalent to nedprealloc2((nedpool *) 0, size, mem, size, 0, M2_RESERVE_MULT(8)) */NEDMALLOCEXTSPEC NEDMALLOCNOALIASATTR NEDMALLOCPTRATTR void * nedrealloc(void *mem, size_t size) THROWSPEC;/*! \brief Equivalent to nedpfree2((nedpool *) 0, mem, 0) */NEDMALLOCEXTSPEC NEDMALLOCNOALIASATTR void nedfree(void *mem) THROWSPEC;/*! \brief Equivalent to nedpmalloc2((nedpool *) 0, size, alignment, 0) */NEDMALLOCEXTSPEC NEDMALLOCNOALIASATTR NEDMALLOCPTRATTR void * nedmemalign(size_t alignment, size_t bytes) THROWSPEC;#if defined(__cplusplus)/*! \ingroup v2malloc\brief Equivalent to nedpmalloc2((nedpool *) 0, size, alignment, flags) */NEDMALLOCEXTSPEC NEDMALLOCNOALIASATTR NEDMALLOCPTRATTR void * nedmalloc2(size_t size, size_t alignment=0, unsigned flags=0) THROWSPEC;/*! \ingroup v2malloc\brief Equivalent to nedprealloc2((nedpool *) 0, mem, size, alignment, flags) */NEDMALLOCEXTSPEC NEDMALLOCNOALIASATTR NEDMALLOCPTRATTR void * nedrealloc2(void *mem, size_t size, size_t alignment=0, unsigned flags=0) THROWSPEC;/*! \ingroup v2malloc\brief Equivalent to nedpfree2((nedpool *) 0, mem, flags) */NEDMALLOCEXTSPEC NEDMALLOCNOALIASATTR void nedfree2(void *mem, unsigned flags=0) THROWSPEC;#elseNEDMALLOCEXTSPEC NEDMALLOCNOALIASATTR NEDMALLOCPTRATTR void * nedmalloc2(size_t size, size_t alignment, unsigned flags) THROWSPEC;NEDMALLOCEXTSPEC NEDMALLOCNOALIASATTR NEDMALLOCPTRATTR void * nedrealloc2(void *mem, size_t size, size_t alignment, unsigned flags) THROWSPEC;NEDMALLOCEXTSPEC NEDMALLOCNOALIASATTR void nedfree2(void *mem, unsigned flags) THROWSPEC;#endif/*! \brief Equivalent to nedpmallinfo((nedpool *) 0) */NEDMALLOCEXTSPEC NEDMALLOCNOALIASATTR struct nedmallinfo nedmallinfo(void) THROWSPEC;/*! \brief Equivalent to nedpmallopt((nedpool *) 0, parno, value) */NEDMALLOCEXTSPEC NEDMALLOCNOALIASATTR int nedmallopt(int parno, int value) THROWSPEC;/*! \brief Returns the internal allocation granularity and the magic header XOR used for internal consistency checks. */NEDMALLOCEXTSPEC NEDMALLOCNOALIASATTR void* nedmalloc_internals(size_t *granularity, size_t *magic) THROWSPEC;/*! \brief Equivalent to nedpmalloc_trim((nedpool *) 0, pad) */NEDMALLOCEXTSPEC NEDMALLOCNOALIASATTR int nedmalloc_trim(size_t pad) THROWSPEC;/*! \brief Equivalent to nedpmalloc_stats((nedpool *) 0) */NEDMALLOCEXTSPEC void nedmalloc_stats(void) THROWSPEC;/*! \brief Equivalent to nedpmalloc_footprint((nedpool *) 0) */NEDMALLOCEXTSPEC NEDMALLOCNOALIASATTR size_t nedmalloc_footprint(void) THROWSPEC;/*! \brief Equivalent to nedpindependent_calloc((nedpool *) 0, elemsno, elemsize, chunks) */NEDMALLOCEXTSPEC NEDMALLOCNOALIASATTR NEDMALLOCPTRATTR void **nedindependent_calloc(size_t elemsno, size_t elemsize, void **chunks) THROWSPEC;/*! \brief Equivalent to nedpindependent_comalloc((nedpool *) 0, elems, sizes, chunks) */NEDMALLOCEXTSPEC NEDMALLOCNOALIASATTR NEDMALLOCPTRATTR void **nedindependent_comalloc(size_t elems, size_t *sizes, void **chunks) THROWSPEC;/*! \brief Destroys the system memory pool used by the functions above.Useful for when you have nedmalloc in a DLL you're about to unload.If you call ANY nedmalloc functions after calling this you willget a fatal exception!*/NEDMALLOCEXTSPEC void neddestroysyspool() THROWSPEC;/*! \brief A nedpool type */struct nedpool_t;/*! \brief A nedpool type */typedef struct nedpool_t nedpool;/*! \brief Creates a memory pool for use with the nedp* functions below.Capacity is how much to allocate immediately (if you know you'll be allocating a lotof memory very soon) which you can leave at zero. Threads specifies how many threadswill *normally* be accessing the pool concurrently. Setting this to zero means itextends on demand, but be careful of this as it can rapidly consume system resourceswhere bursts of concurrent threads use a pool at once.*/NEDMALLOCEXTSPEC NEDMALLOCNOALIASATTR NEDMALLOCPTRATTR nedpool *nedcreatepool(size_t capacity, int threads) THROWSPEC;/*! \brief Destroys a memory pool previously created by nedcreatepool().*/NEDMALLOCEXTSPEC void neddestroypool(nedpool *p) THROWSPEC;/*! \brief Returns a zero terminated snapshot of threadpools existing at the time of call.Call nedfree() on the returned list when you are done. Returns zero if there is only thesystem pool in existence.*/NEDMALLOCEXTSPEC nedpool **nedpoollist() THROWSPEC;/*! \brief Sets a value to be associated with a pool.You can retrieve this value by passing any memory block allocated from that pool.*/NEDMALLOCEXTSPEC void nedpsetvalue(nedpool *p, void *v) THROWSPEC;/*! \brief Gets a previously set value using nedpsetvalue() or zero if memory is unknown.Optionally can also retrieve pool. You can detect an unknown block by the returnbeing zero and *p being unmodifed.*/NEDMALLOCEXTSPEC void *nedgetvalue(nedpool **p, void *mem) THROWSPEC;/*! \brief Trims the thread cache for the calling thread, returning any existing cachedata to the central pool.Remember to ALWAYS call with zero if you used the system pool. Setting disable tonon-zero replicates neddisablethreadcache().*/NEDMALLOCEXTSPEC void nedtrimthreadcache(nedpool *p, int disable) THROWSPEC;/*! \brief Disables the thread cache for the calling thread, returning any existing cachedata to the central pool.Remember to ALWAYS call with zero if you used the system pool.*/NEDMALLOCEXTSPEC void neddisablethreadcache(nedpool *p) THROWSPEC;/*! \brief Releases all memory in all threadcaches in the pool, and writes allaccumulated memory operations to the log if enabled.You can pass zero for filepath to use the compiled default, or else a char[MAX_PATH]containing the path you wish to use for the log file. The log file is alwaysappended to if it already exists. After writing the logs, the logging abilityis disabled for that pool.\warning Do NOT call this if the pool is in use - this call is NOT threadsafe.*/NEDMALLOCEXTSPEC size_t nedflushlogs(nedpool *p, char *filepath) THROWSPEC;/*! \brief Equivalent to nedpmalloc2(p, size, 0, 0) */NEDMALLOCEXTSPEC NEDMALLOCNOALIASATTR NEDMALLOCPTRATTR void * nedpmalloc(nedpool *p, size_t size) THROWSPEC;/*! \brief Equivalent to nedpmalloc2(p, no*size, 0, M2_ZERO_MEMORY) */NEDMALLOCEXTSPEC NEDMALLOCNOALIASATTR NEDMALLOCPTRATTR void * nedpcalloc(nedpool *p, size_t no, size_t size) THROWSPEC;/*! \brief Equivalent to nedprealloc2(p, mem, size, 0, M2_RESERVE_MULT(8)) */NEDMALLOCEXTSPEC NEDMALLOCNOALIASATTR NEDMALLOCPTRATTR void * nedprealloc(nedpool *p, void *mem, size_t size) THROWSPEC;/*! \brief Equivalent to nedpfree2(p, mem, 0) */NEDMALLOCEXTSPEC NEDMALLOCNOALIASATTR void nedpfree(nedpool *p, void *mem) THROWSPEC;/*! \brief Equivalent to nedpmalloc2(p, bytes, alignment, 0) */NEDMALLOCEXTSPEC NEDMALLOCNOALIASATTR NEDMALLOCPTRATTR void * nedpmemalign(nedpool *p, size_t alignment, size_t bytes) THROWSPEC;#if defined(__cplusplus)/*! \ingroup v2malloc\brief Allocates a block of memory sized \em size from pool \em p, aligned to \em alignment and according to the flags \em flags.*/NEDMALLOCEXTSPEC NEDMALLOCNOALIASATTR NEDMALLOCPTRATTR void * nedpmalloc2(nedpool *p, size_t size, size_t alignment=0, unsigned flags=0) THROWSPEC;/*! \ingroup v2malloc\brief Resizes the block of memory at \em mem in pool \em p to size \em size, aligned to \em alignment and according to the flags \em flags.*/NEDMALLOCEXTSPEC NEDMALLOCNOALIASATTR NEDMALLOCPTRATTR void * nedprealloc2(nedpool *p, void *mem, size_t size, size_t alignment=0, unsigned flags=0) THROWSPEC;/*! \brief Frees the block \em mem from the pool \em p according to flags \em flags. */NEDMALLOCEXTSPEC NEDMALLOCNOALIASATTR void nedpfree2(nedpool *p, void *mem, unsigned flags=0) THROWSPEC;#elseNEDMALLOCEXTSPEC NEDMALLOCNOALIASATTR NEDMALLOCPTRATTR void * nedpmalloc2(nedpool *p, size_t size, size_t alignment, unsigned flags) THROWSPEC;NEDMALLOCEXTSPEC NEDMALLOCNOALIASATTR NEDMALLOCPTRATTR void * nedprealloc2(nedpool *p, void *mem, size_t size, size_t alignment, unsigned flags) THROWSPEC;NEDMALLOCEXTSPEC NEDMALLOCNOALIASATTR void nedpfree2(nedpool *p, void *mem, unsigned flags) THROWSPEC;#endif/*! \brief Returns information about the memory pool */NEDMALLOCEXTSPEC struct nedmallinfo nedpmallinfo(nedpool *p) THROWSPEC;/*! \brief Changes the operational parameters of the memory pool */NEDMALLOCEXTSPEC int nedpmallopt(nedpool *p, int parno, int value) THROWSPEC;/*! \brief Tries to release as much free memory back to the system as possible, leaving \em pad remaining per threadpool. */NEDMALLOCEXTSPEC int nedpmalloc_trim(nedpool *p, size_t pad) THROWSPEC;/*! \brief Prints some operational statistics to stdout. */NEDMALLOCEXTSPEC void nedpmalloc_stats(nedpool *p) THROWSPEC;/*! \brief Returns how much memory is currently in use by the memory pool */NEDMALLOCEXTSPEC size_t nedpmalloc_footprint(nedpool *p) THROWSPEC;/*! \brief Returns a series of guaranteed consecutive cleared memory allocations.independent_calloc is similar to calloc, but instead of returning asingle cleared space, it returns an array of pointers to n_elementsindependent elements that can hold contents of size elem_size, eachof which starts out cleared, and can be independently freed,realloc'ed etc. The elements are guaranteed to be adjacentlyallocated (this is not guaranteed to occur with multiple callocs ormallocs), which may also improve cache locality in someapplications.The "chunks" argument is optional (i.e., may be null, which isprobably the most typical usage). If it is null, the returned arrayis itself dynamically allocated and should also be freed when it isno longer needed. Otherwise, the chunks array must be of at leastn_elements in length. It is filled in with the pointers to thechunks.In either case, independent_calloc returns this pointer array, ornull if the allocation failed. If n_elements is zero and "chunks"is null, it returns a chunk representing an array with zero elements(which should be freed if not wanted).Each element must be individually freed when it is no longerneeded. If you'd like to instead be able to free all at once, youshould instead use regular calloc and assign pointers into thisspace to represent elements. (In this case though, you cannotindependently free elements.)independent_calloc simplifies and speeds up implementations of manykinds of pools. It may also be useful when constructing large datastructures that initially have a fixed number of fixed-sized nodes,but the number is not known at compile time, and some of the nodesmay later need to be freed. For example:struct Node { int item; struct Node* next; };struct Node* build_list() {struct Node** pool;int n = read_number_of_nodes_needed();if (n <= 0) return 0;pool = (struct Node**)(independent_calloc(n, sizeof(struct Node), 0);if (pool == 0) die();// organize into a linked list...struct Node* first = pool[0];for (i = 0; i < n-1; ++i)pool[i]->next = pool[i+1];free(pool); // Can now free the array (or not, if it is needed later)return first;}*/NEDMALLOCEXTSPEC NEDMALLOCNOALIASATTR NEDMALLOCPTRATTR void **nedpindependent_calloc(nedpool *p, size_t elemsno, size_t elemsize, void **chunks) THROWSPEC;/*! \brief Returns a series of guaranteed consecutive allocations.independent_comalloc allocates, all at once, a set of n_elementschunks with sizes indicated in the "sizes" array. It returnsan array of pointers to these elements, each of which can beindependently freed, realloc'ed etc. The elements are guaranteed tobe adjacently allocated (this is not guaranteed to occur withmultiple callocs or mallocs), which may also improve cache localityin some applications.The "chunks" argument is optional (i.e., may be null). If it is nullthe returned array is itself dynamically allocated and should alsobe freed when it is no longer needed. Otherwise, the chunks arraymust be of at least n_elements in length. It is filled in with thepointers to the chunks.In either case, independent_comalloc returns this pointer array, ornull if the allocation failed. If n_elements is zero and chunks isnull, it returns a chunk representing an array with zero elements(which should be freed if not wanted).Each element must be individually freed when it is no longerneeded. If you'd like to instead be able to free all at once, youshould instead use a single regular malloc, and assign pointers atparticular offsets in the aggregate space. (In this case though, youcannot independently free elements.)independent_comallac differs from independent_calloc in that eachelement may have a different size, and also that it does notautomatically clear elements.independent_comalloc can be used to speed up allocation in caseswhere several structs or objects must always be allocated at thesame time. For example:struct Head { ... }struct Foot { ... }void send_message(char* msg) {int msglen = strlen(msg);size_t sizes[3] = { sizeof(struct Head), msglen, sizeof(struct Foot) };void* chunks[3];if (independent_comalloc(3, sizes, chunks) == 0)die();struct Head* head = (struct Head*)(chunks[0]);char* body = (char*)(chunks[1]);struct Foot* foot = (struct Foot*)(chunks[2]);// ...}In general though, independent_comalloc is worth using only forlarger values of n_elements. For small values, you probably won'tdetect enough difference from series of malloc calls to bother.Overuse of independent_comalloc can increase overall memory usage,since it cannot reuse existing noncontiguous small chunks thatmight be available for some of the elements.*/NEDMALLOCEXTSPEC NEDMALLOCNOALIASATTR NEDMALLOCPTRATTR void **nedpindependent_comalloc(nedpool *p, size_t elems, size_t *sizes, void **chunks) THROWSPEC;#if defined(__cplusplus)} /* namespace or extern "C" */#include <new>#include <memory>#ifdef HAVE_CPP0XTYPETRAITS#include <type_traits>#endif// Touch into existence for future platformsnamespace std { namespace tr1 { } }/*! \defgroup C++ C++ language supportThanks to the generous support of Applied Research Associates (USA), nedalloc has extensiveC++ language support which uses C++ metaprogramming techniques to provide a policy drivenSTL container reimplementor. The metaprogramming silently overrides or replaces the STL implementationon your system (MSVC and GCC are the two currently supported) to \b substantially improvethe performance of STL containers by making use of nedalloc's additional features.Sounds difficult to use? Not really. Simply do this:\codeusing namespace nedalloc;typedef nedallocatorise<std::vector, unsigned int,nedpolicy::typeIsPOD<true>::policy,nedpolicy::mmap<>::policy,nedpolicy::reserveN<26>::policy // 1<<26 = 64Mb. 10,000,000 * sizeof(unsigned int) = 38Mb.>::value myvectortype;myvectortype a;for(int n=0; n<10000000; n++)a.push_back(n);\endcodeThe metaprogramming requires a new C++ compiler (> year 2008), and it will readily make useof a C++0x compiler where it will use rvalue referencing, variadic templates, type traits and more.Visual Studio 2008 or later is sufficent, as is GCC v4.4 or later.nedalloc's metaprogramming is designed to be extensible, so the rest of this page is intended for thosewishing to customise the metaprogramming. If you simply wish to know how to use thenedalloc::nedallocator STL allocator or the nedalloc::nedallocatorise STL reimplementor, please referto test.cpp which gives several examples of usage.<h2>Extending the metaprogramming:</h2>A nedallocator policy looks as follows:\codenamespace nedpolicy {template<size_t size, size_t alignment> struct sizedalign{template<class Base> class policy : public Base{template<class implementation> friend class nedallocatorI::baseimplementation;protected:size_t policy_alignment(size_t bytes) const{return (bytes < size) ? alignment : 0;}};};}\endcodeThe policy above implements a size based alignment, so if the block being allocated isless than \em size then it causes \em alignment to be used, otherwise it does not align.The sizedalign struct is merely a template parameter encapsulator used to captureadditional parameters, so the real policy is in fact the class policy held within in.If you did not need to specify any additional parameters e.g. if you were definingpolicy_nedpool(), then you would directly define a policy returning your nedpool and passit directly to nedallocator<>.The primary policy functions which are intended to be overridden are listed innedalloc::nedallocatorI::baseimplementation in nedmalloc.h and are prefixed by "policy_".However, there is absolutely no reason why the meatier functions such asnedalloc::nedallocatorI::baseimplementation::allocate() cannot be overriden, and indeedsome of the policies defined in nedmalloc.h do just that.Policy composition is handled by a dedicated recursive variadic template callednedalloc::nedallocatorI::policycompositor. If you have \em really specialised needs, youcan partially specialise this class to make it do all sorts of interesting things - henceits separation into its own class.*//*! \brief The nedalloc namespace */namespace nedalloc {/*! \def NEDSTATIC_ASSERT(expr, msg)\brief Generates a static assertion if (expr)==0 at compile time.Make SURE your message contains no spaces or anything else which would make it an invalidvariable name.*/#ifndef HAVE_CPP0XSTATICASSERTtemplate<bool> struct StaticAssert;template<> struct StaticAssert<true>{StaticAssert() { }};#define NEDSTATIC_ASSERT(expr, msg) \nedalloc::StaticAssert<(expr)!=0> ERROR_##msg#else#define NEDSTATIC_ASSERT(expr, msg) static_assert((expr)!=0, #msg )#endif/*! \brief The policy namespace in which all nedallocator policies live. */namespace nedpolicy {/*! \class empty\ingroup C++\brief An empty policy which does nothing.*/template<class Base> class empty : public Base{};}/*! \brief The implementation namespace where the internals live. */namespace nedallocatorI{using namespace std;using namespace tr1;/* Roll on variadic templates is all I can say! */#ifdef HAVE_CPP0XVARIADICTEMPLATEStemplate<class Impl, template<class> class... policies> class policycompositor;template<class Impl, template<class> class A, template<class> class... policies> class policycompositor<Impl, A, policies...>{typedef policycompositor<Impl, policies...> temp;public:typedef A<typename temp::value> value;};#elsetemplate<class Impl,template<class> class A=nedpolicy::empty,template<class> class B=nedpolicy::empty,template<class> class C=nedpolicy::empty,template<class> class D=nedpolicy::empty,template<class> class E=nedpolicy::empty,template<class> class F=nedpolicy::empty,template<class> class G=nedpolicy::empty,template<class> class H=nedpolicy::empty,template<class> class I=nedpolicy::empty,template<class> class J=nedpolicy::empty,template<class> class K=nedpolicy::empty,template<class> class L=nedpolicy::empty,template<class> class M=nedpolicy::empty,template<class> class N=nedpolicy::empty,template<class> class O=nedpolicy::empty> class policycompositor{typedef policycompositor<Impl, B, C, D, E, F, G, H, I, J, K, L, M, N, O> temp;public:typedef A<typename temp::value> value;};#endiftemplate<class Impl> class policycompositor<Impl>{public:typedef Impl value;};}template<typename T,#ifdef HAVE_CPP0XVARIADICTEMPLATEStemplate<class> class... policies#elsetemplate<class> class policy1=nedpolicy::empty,template<class> class policy2=nedpolicy::empty,template<class> class policy3=nedpolicy::empty,template<class> class policy4=nedpolicy::empty,template<class> class policy5=nedpolicy::empty,template<class> class policy6=nedpolicy::empty,template<class> class policy7=nedpolicy::empty,template<class> class policy8=nedpolicy::empty,template<class> class policy9=nedpolicy::empty,template<class> class policy10=nedpolicy::empty,template<class> class policy11=nedpolicy::empty,template<class> class policy12=nedpolicy::empty,template<class> class policy13=nedpolicy::empty,template<class> class policy14=nedpolicy::empty,template<class> class policy15=nedpolicy::empty#endif> class nedallocator;namespace nedallocatorI{/*! \brief The base implementation class */template<class implementation> class baseimplementation{//NEDSTATIC_ASSERT(false, Bad_policies_specified);};/*! \brief The base implementation class */template<typename T,#ifdef HAVE_CPP0XVARIADICTEMPLATEStemplate<class> class... policies#elsetemplate<class> class policy1,template<class> class policy2,template<class> class policy3,template<class> class policy4,template<class> class policy5,template<class> class policy6,template<class> class policy7,template<class> class policy8,template<class> class policy9,template<class> class policy10,template<class> class policy11,template<class> class policy12,template<class> class policy13,template<class> class policy14,template<class> class policy15#endif> class baseimplementation<nedallocator<T,#ifdef HAVE_CPP0XVARIADICTEMPLATESpolicies...#elsepolicy1, policy2, policy3, policy4, policy5,policy6, policy7, policy8, policy9, policy10,policy11, policy12, policy13, policy14, policy15#endif> >{protected://! \brief The most derived nedallocator implementation typetypedef nedallocator<T,#ifdef HAVE_CPP0XVARIADICTEMPLATESpolicies...#elsepolicy1, policy2, policy3, policy4, policy5,policy6, policy7, policy8, policy9, policy10,policy11, policy12, policy13, policy14, policy15#endif> implementationType;//! \brief Returns a this for the most derived nedallocator implementation typeimplementationType *_this() { return static_cast<implementationType *>(this); }//! \brief Returns a this for the most derived nedallocator implementation typeconst implementationType *_this() const { return static_cast<const implementationType *>(this); }//! \brief Specifies the nedpool to use. Defaults to zero (the system pool).nedpool *policy_nedpool(size_t bytes) const{return 0;}//! \brief Specifies the granularity to use. Defaults to \em bytes (no granularity).size_t policy_granularity(size_t bytes) const{return bytes;}//! \brief Specifies the alignment to use. Defaults to zero (no alignment).size_t policy_alignment(size_t bytes) const{return 0;}//! \brief Specifies the flags to use. Defaults to zero (no flags).unsigned policy_flags(size_t bytes) const{return 0;}//! \brief Specifies what to do when the allocation fails. Defaults to throwing std::bad_alloc.void policy_throwbadalloc(size_t bytes) const{throw std::bad_alloc();}//! \brief Specifies if the type is POD. Is std::is_trivially_copyable<T>::value on C++0x compilers, otherwise false.static const bool policy_typeIsPOD=#ifdef HAVE_CPP0XTYPETRAITS#if defined(__GNUC__) && (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) < 40900is_pod<T>::value;#elseis_trivially_copyable<T>::value;#endif#elsefalse;#endifpublic:typedef T *pointer;typedef const T *const_pointer;typedef T &reference;typedef const T &const_reference;typedef T value_type;typedef size_t size_type;typedef ptrdiff_t difference_type;T *address(T &r) const { return &r; }const T *address(const T &s) const { return &s; }size_t max_size() const { return (static_cast<size_t>(0) - static_cast<size_t>(1)) / sizeof(T); }bool operator!=(const baseimplementation &other) const { return !(*this == other); }bool operator==(const baseimplementation &other) const { return true; }void construct(T *const p, const T &t) const {void *const _p = static_cast<void *>(p);new (_p) T(t);}void destroy(T *const p) const {p->~T();}baseimplementation() { }baseimplementation(const baseimplementation &) { }#ifdef HAVE_CPP0XRVALUEREFSbaseimplementation(baseimplementation &&) { }#endiftemplate<typename U> struct rebind {typedef nedallocator<U,#ifdef HAVE_CPP0XVARIADICTEMPLATESpolicies...#elsepolicy1, policy2, policy3, policy4, policy5,policy6, policy7, policy8, policy9, policy10,policy11, policy12, policy13, policy14, policy15#endif> other;};template<typename U> baseimplementation(const nedallocator<U,#ifdef HAVE_CPP0XVARIADICTEMPLATESpolicies...#elsepolicy1, policy2, policy3, policy4, policy5,policy6, policy7, policy8, policy9, policy10,policy11, policy12, policy13, policy14, policy15#endif> &) { }T *allocate(const size_t n) const {// Leave these spelled out to aid debuggingconst size_t t_size = sizeof(T);size_t size = _this()->policy_granularity(n*t_size);nedpool *pool = _this()->policy_nedpool(size);size_t alignment = _this()->policy_alignment(size);unsigned flags = _this()->policy_flags(size);void *ptr = nedpmalloc2(pool, size, alignment, flags);if(!ptr)_this()->policy_throwbadalloc(size);return static_cast<T *>(ptr);}void deallocate(T *p, const size_t n) const {nedpfree(0/*not needed*/, p);}template<typename U> T *allocate(const size_t n, const U * /* hint */) const {return allocate(n);}private:baseimplementation &operator=(const baseimplementation &);};}namespace nedpolicy{/*! \class granulate\ingroup C++\brief A policy setting the granularity of the allocated memory.Memory is sized according to (size+granularity-1) & ~(granularity-1).In other words, granularity \b must be a power of two.*/template<size_t granularity> struct granulate{template<class Base> class policy : public Base{template<class implementation> friend class nedallocatorI::baseimplementation;protected:size_t policy_granularity(size_t bytes) const{return (bytes+granularity-1) & ~(granularity-1);}};};/*! \class align\ingroup C++\brief A policy setting the alignment of the allocated memory.*/template<size_t alignment> struct align{template<class Base> class policy : public Base{template<class implementation> friend class nedallocatorI::baseimplementation;protected:size_t policy_alignment(size_t bytes) const{return alignment;}};};/*! \class zero\ingroup C++\brief A policy causing the zeroing of the allocated memory.*/template<bool dozero=true> struct zero{template<class Base> class policy : public Base{template<class implementation> friend class nedallocatorI::baseimplementation;protected:unsigned policy_flags(size_t bytes) const{return dozero ? Base::policy_flags(bytes)|M2_ZERO_MEMORY : Base::policy_flags(bytes);}};};/*! \class preventmove\ingroup C++\brief A policy preventing the moving of the allocated memory.*/template<bool doprevent=true> struct preventmove{template<class Base> class policy : public Base{template<class implementation> friend class nedallocatorI::baseimplementation;protected:unsigned policy_flags(size_t bytes) const{return doprevent ? Base::policy_flags(bytes)|M2_PREVENT_MOVE : Base::policy_flags(bytes);}};};/*! \class mmap\ingroup C++\brief A policy causing the mmapping of the allocated memory.*/template<bool dommap=true> struct mmap{template<class Base> class policy : public Base{template<class implementation> friend class nedallocatorI::baseimplementation;protected:unsigned policy_flags(size_t bytes) const{return dommap ? Base::policy_flags(bytes)|M2_ALWAYS_MMAP : Base::policy_flags(bytes);}};};/*! \class reserveX\ingroup C++\brief A policy causing the address reservation of X times the allocated memory.*/template<size_t X> struct reserveX{template<class Base> class policy : public Base{template<class implementation> friend class nedallocatorI::baseimplementation;protected:unsigned policy_flags(size_t bytes) const{return Base::policy_flags(bytes)|M2_RESERVE_MULT(X);}};};/*! \class reserveN\ingroup C++\brief A policy causing the address reservation of (1<<N) bytes of memory.*/template<size_t N> struct reserveN{template<class Base> class policy : public Base{template<class implementation> friend class nedallocatorI::baseimplementation;protected:unsigned policy_flags(size_t bytes) const{return Base::policy_flags(bytes)|M2_RESERVE_SHIFT(N);}};};/*! \class badalloc\ingroup C++\brief A policy specifying what to throw when an allocation failure occurs.A type specialisation exists for badalloc<void> which is equivalent to new(nothrow)i.e. return zero and don't throw anything.*/template<typename T> struct badalloc{template<class Base> class policy : public Base{template<class implementation> friend class nedallocatorI::baseimplementation;protected:void policy_throwbadalloc(size_t bytes) const{throw T();}};};template<> struct badalloc<void>{template<class Base> class policy : public Base{template<class implementation> friend class nedallocatorI::baseimplementation;protected:void policy_throwbadalloc(size_t bytes) const{}};};/*! \class typeIsPOD\ingroup C++\brief A policy forcing the treatment of the type as Plain Old Data (POD)On C++0x compilers, the <type_traits> is_trivially_copyable<type>::value is used by default.When treated as POD, memcpy() is used insteadof copy construction and realloc() is permitted to move the memory contents whenresizing.*/template<bool ispod> struct typeIsPOD{template<class Base> class policy : public Base{template<class implementation> friend class nedallocatorI::baseimplementation;protected:static const bool policy_typeIsPOD=ispod;};};}/*! \class nedallocator\ingroup C++\brief A policy driven STL allocator which uses nedmallocOne of the lesser known features of STL container classes is their ability to takean allocator implementation class, so where you had std::vector<Foo> you can nowhave std::vector<Foo, nedalloc::nedallocator< std::vector<Foo> > such thatstd::vector<> will now use nedalloc as the policy specifies.You <b>almost certainly</b> don't want to use this directly except in the naivecase. See nedalloc::nedallocatorise to see what I mean.*/template<typename T,#ifdef HAVE_CPP0XVARIADICTEMPLATEStemplate<class> class... policies#elsetemplate<class> class policy1,template<class> class policy2,template<class> class policy3,template<class> class policy4,template<class> class policy5,template<class> class policy6,template<class> class policy7,template<class> class policy8,template<class> class policy9,template<class> class policy10,template<class> class policy11,template<class> class policy12,template<class> class policy13,template<class> class policy14,template<class> class policy15#endif> class nedallocator : public nedallocatorI::policycompositor<#ifdef HAVE_CPP0XVARIADICTEMPLATESnedallocatorI::baseimplementation<nedallocator<T, policies...> >,policies...#elsenedallocatorI::baseimplementation<nedallocator<T,policy1, policy2, policy3, policy4, policy5,policy6, policy7, policy8, policy9, policy10,policy11, policy12, policy13, policy14, policy15> >,policy1, policy2, policy3, policy4, policy5,policy6, policy7, policy8, policy9, policy10,policy11, policy12, policy13, policy14, policy15#endif>::value{typedef typename nedallocatorI::policycompositor<#ifdef HAVE_CPP0XVARIADICTEMPLATESnedallocatorI::baseimplementation<nedallocator<T, policies...> >,policies...#elsenedallocatorI::baseimplementation<nedallocator<T,policy1, policy2, policy3, policy4, policy5,policy6, policy7, policy8, policy9, policy10,policy11, policy12, policy13, policy14, policy15> >,policy1, policy2, policy3, policy4, policy5,policy6, policy7, policy8, policy9, policy10,policy11, policy12, policy13, policy14, policy15#endif>::value Base;public:nedallocator() { }nedallocator(const nedallocator &o) : Base(o) { }#ifdef HAVE_CPP0XRVALUEREFSnedallocator(nedallocator &&o) : Base(std::move(o)) { }#endif/* This templated constructor and rebind() are used by MSVC's secure iterator checker.I think it's best to not copy state even though it may break policies which store data. */template<typename U> nedallocator(const nedallocator<U,#ifdef HAVE_CPP0XVARIADICTEMPLATESpolicies...#elsepolicy1, policy2, policy3, policy4, policy5,policy6, policy7, policy8, policy9, policy10,policy11, policy12, policy13, policy14, policy15#endif> &o) { }#ifdef HAVE_CPP0XRVALUEREFStemplate<typename U> nedallocator(nedallocator<U,#ifdef HAVE_CPP0XVARIADICTEMPLATESpolicies...#elsepolicy1, policy2, policy3, policy4, policy5,policy6, policy7, policy8, policy9, policy10,policy11, policy12, policy13, policy14, policy15#endif> &&o) { }#endiftemplate<typename U> struct rebind {typedef nedallocator<U,#ifdef HAVE_CPP0XVARIADICTEMPLATESpolicies...#elsepolicy1, policy2, policy3, policy4, policy5,policy6, policy7, policy8, policy9, policy10,policy11, policy12, policy13, policy14, policy15#endif> other;};};namespace nedallocatorI {// Holds a static allocator instance shared by anything allocating from allocatortemplate<class allocator> struct StaticAllocator{static allocator &get(){static allocator a;return a;}};// RAII holder for a Newed objecttemplate<typename T, class allocator> struct PtrHolder{T *mem;PtrHolder(T *_mem) : mem(_mem) { }~PtrHolder(){if(mem){allocator &a=nedallocatorI::StaticAllocator<allocator>::get();a.deallocate(mem, sizeof(T));mem=0;}}T *release() { T *ret=mem; mem=0; return ret; }T *operator *() { return mem; }const T *operator *() const { return mem; }};}/*! \brief Allocates the memory for an instance of object \em T and constructs it.If an exception is thrown during construction, the memory is freed beforerethrowing the exception.Usage is very simple:\codeSSEVectorType *foo1=New<SSEVectorType>(4, 5, 6, 7);\endcode*/#ifdef HAVE_CPP0XVARIADICTEMPLATEStemplate<typename T, class allocator=nedallocator<T>, typename... Parameters> inline T *New(const Parameters&... parameters)#elsetemplate<typename T, class allocator> inline T *New()#endif{allocator &a=nedallocatorI::StaticAllocator<allocator>::get();nedallocatorI::PtrHolder<T, allocator> ret(a.allocate(sizeof(T)));if(*ret){#ifdef HAVE_CPP0XVARIADICTEMPLATESnew((void *) *ret) T(parameters...);#elsenew((void *) *ret) T;#endif}return ret.release();}#ifndef HAVE_CPP0XVARIADICTEMPLATES// Extremely annoying not to have default template arguments for functions pre-C++0xtemplate<typename T> inline T *New(){return New<T, nedallocator<T> >();}// Also, it's painful to replicate function overloads :(#define NEDMALLOC_NEWIMPL \template<typename T, class allocator, NEDMALLOC_NEWIMPLTYPES> inline T *New(NEDMALLOC_NEWIMPLPARSDEFS) \{ \allocator &a=nedallocatorI::StaticAllocator<allocator>::get(); \nedallocatorI::PtrHolder<T, allocator> ret(a.allocate(sizeof(T))); \if(*ret) \{ \new((void *) *ret) T(NEDMALLOC_NEWIMPLPARS); \} \return ret.release(); \} \template<typename T, NEDMALLOC_NEWIMPLTYPES> inline T *New(NEDMALLOC_NEWIMPLPARSDEFS)\{ \return New<T, nedallocator<T> >(NEDMALLOC_NEWIMPLPARS); \}#define NEDMALLOC_NEWIMPLTYPES typename P1#define NEDMALLOC_NEWIMPLPARSDEFS const P1 &p1#define NEDMALLOC_NEWIMPLPARS p1NEDMALLOC_NEWIMPL#undef NEDMALLOC_NEWIMPLTYPES#undef NEDMALLOC_NEWIMPLPARSDEFS#undef NEDMALLOC_NEWIMPLPARS#define NEDMALLOC_NEWIMPLTYPES typename P1, typename P2#define NEDMALLOC_NEWIMPLPARSDEFS const P1 &p1, const P2 &p2#define NEDMALLOC_NEWIMPLPARS p1, p2NEDMALLOC_NEWIMPL#undef NEDMALLOC_NEWIMPLTYPES#undef NEDMALLOC_NEWIMPLPARSDEFS#undef NEDMALLOC_NEWIMPLPARS#define NEDMALLOC_NEWIMPLTYPES typename P1, typename P2, typename P3#define NEDMALLOC_NEWIMPLPARSDEFS const P1 &p1, const P2 &p2, const P3 &p3#define NEDMALLOC_NEWIMPLPARS p1, p2, p3NEDMALLOC_NEWIMPL#undef NEDMALLOC_NEWIMPLTYPES#undef NEDMALLOC_NEWIMPLPARSDEFS#undef NEDMALLOC_NEWIMPLPARS#define NEDMALLOC_NEWIMPLTYPES typename P1, typename P2, typename P3, typename P4#define NEDMALLOC_NEWIMPLPARSDEFS const P1 &p1, const P2 &p2, const P3 &p3, const P4 &p4#define NEDMALLOC_NEWIMPLPARS p1, p2, p3, p4NEDMALLOC_NEWIMPL#undef NEDMALLOC_NEWIMPLTYPES#undef NEDMALLOC_NEWIMPLPARSDEFS#undef NEDMALLOC_NEWIMPLPARS#define NEDMALLOC_NEWIMPLTYPES typename P1, typename P2, typename P3, typename P4, typename P5#define NEDMALLOC_NEWIMPLPARSDEFS const P1 &p1, const P2 &p2, const P3 &p3, const P4 &p4, const P5 &p5#define NEDMALLOC_NEWIMPLPARS p1, p2, p3, p4, p5NEDMALLOC_NEWIMPL#undef NEDMALLOC_NEWIMPLTYPES#undef NEDMALLOC_NEWIMPLPARSDEFS#undef NEDMALLOC_NEWIMPLPARS#undef NEDMALLOC_NEWIMPL#endif/*! \brief Destructs an instance of object T, and releases the memory used to store it.*/template<class allocator, typename T> inline void Delete(const T *_obj){T *obj=const_cast<T *>(_obj);allocator &a=nedallocatorI::StaticAllocator<allocator>::get();obj->~T();a.deallocate(obj, sizeof(T));}template<typename T> inline void Delete(const T *obj) { Delete<nedallocator<T> >(obj); }/*! \class nedallocatorise\ingroup C++\brief Reimplements a given STL container to make full and efficient usage of nedalloc\param stlcontainer The STL container you wish to reimplement\param T The type to be contained\param policies... Any policies you want applied to the allocatorThis is a clever bit of C++ metaprogramming if I do say so myself! What it doesis to specialise a STL container implementation to make full use of nedalloc'sadvanced facilities, so for example if you do:\codeusing namespace nedalloc;typedef nedallocatorise<std::vector, unsigned int,nedpolicy::typeIsPOD<true>::policy,nedpolicy::mmap<>::policy,nedpolicy::reserveN<26>::policy // 1<<26 = 64Mb. 10,000,000 * sizeof(unsigned int) = 38Mb.>::value myvectortype;myvectortype a;for(int n=0; n<10000000; n++)a.push_back(n);\endcodeWhat happens here is that nedallocatorise reimplements the parts ofstd::vector which extend and shrink the actual memory allocation.Because the typeIsPOD policy is specified, it means that realloc()rather than realloc(M2_PREVENT_MOVE) can be used. Also, because themmap and the reserveN policies are specified, std::vector immediatelyreserves 64Mb of address space and forces the immediate use of mmap().This allows you to push_back() a lot of data very, very quickly indeed.You will also find that pop_back() actually reduces the allocation now(most implementations don't bother ever releasing memory except whenreaching empty or when resize() is called). When mmapped, reserve()is automatically held at a minimum of <page size>/sizeof(type) thoughlarger values are respected.test.cpp has a benchmark of the speed differences you may realise, plusan example of usage.*/template<template<typename, class> class stlcontainer,typename T,#ifdef HAVE_CPP0XVARIADICTEMPLATEStemplate<class> class... policies#elsetemplate<class> class policy1=nedpolicy::empty,template<class> class policy2=nedpolicy::empty,template<class> class policy3=nedpolicy::empty,template<class> class policy4=nedpolicy::empty,template<class> class policy5=nedpolicy::empty,template<class> class policy6=nedpolicy::empty,template<class> class policy7=nedpolicy::empty,template<class> class policy8=nedpolicy::empty,template<class> class policy9=nedpolicy::empty,template<class> class policy10=nedpolicy::empty,template<class> class policy11=nedpolicy::empty,template<class> class policy12=nedpolicy::empty,template<class> class policy13=nedpolicy::empty,template<class> class policy14=nedpolicy::empty,template<class> class policy15=nedpolicy::empty#endif> class nedallocatorise{public://! The reimplemented STL container typetypedef stlcontainer<T, nedallocator<T,#ifdef HAVE_CPP0XVARIADICTEMPLATESpolicies...#elsepolicy1, policy2, policy3, policy4, policy5,policy6, policy7, policy8, policy9, policy10,policy11, policy12, policy13, policy14, policy15#endif> > value;};} /* namespace */#endif/* Some miscellaneous dlmalloc option documentation */#ifdef DOXYGEN_IS_PARSING_ME/* Just some false defines to keep doxygen happy */#define NEDMALLOC_DEBUG DEBUG#define ENABLE_LARGE_PAGES undef#define ENABLE_FAST_HEAP_DETECTION undef#define REPLACE_SYSTEM_ALLOCATOR undef#define ENABLE_TOLERANT_NEDMALLOC undef#define NO_NED_NAMESPACE undef/*! \def MALLOC_ALIGNMENT\brief Defines what alignment normally returned blocks should use. Is 16 bytes on Mac OS X, otherwise 8 bytes. */#define MALLOC_ALIGNMENT 8/*! \def USE_LOCKS\brief Defines the threadsafety of nedallocUSE_LOCKS can be 2 if you want to define your own MLOCK_T, INITIAL_LOCK,ACQUIRE_LOCK, RELEASE_LOCK, TRY_LOCK, IS_LOCKED and NULL_LOCK_INITIALIZER.*/#define USE_LOCKS 1/*! \def DEFAULT_GRANULARITY\brief Defines the granularity in which to request or free system memory.*/#define DEFAULT_GRANULARITY (2*1024*1024)/*! \def DEFAULT_TRIM_THRESHOLD\brief Defines how much memory must be free before returning it to the system.*/#define DEFAULT_TRIM_THRESHOLD (2*1024*1024)/*! \def DEFAULT_MMAP_THRESHOLD\brief Defines the threshold above which mmap() is used to perform direct allocation.*/#define DEFAULT_MMAP_THRESHOLD (256*1024)/*! \def MAX_RELEASE_CHECK_RATE\brief Defines how many free() ops should occur before checking how much free memory there is.*/#define MAX_RELEASE_CHECK_RATE 4095/*! \def NEDMALLOC_FORCERESERVE\brief Lets you force address space reservation in the \b standard malloc APINote that by default realloc() sets M2_RESERVE_MULT(8) when thunking to realloc2(),so you probably don't need to override this*/#define NEDMALLOC_FORCERESERVE(p, mem, size) 0/*! \def NEDMALLOC_TESTLOGENTRY\brief Used to determine whether a given memory operation should be logged.*/#define NEDMALLOC_TESTLOGENTRY(tc, np, type, mspace, size, mem, alignment, flags, returned) ((type)&ENABLE_LOGGING)/*! \def NEDMALLOC_STACKBACKTRACEDEPTH\brief Turns on stack backtracing in the logger.You almost certainly want to constrain what gets logged using NEDMALLOC_TESTLOGENTRYif you turn this on as the sheer volume of data output can make execution very slow.*/#define NEDMALLOC_STACKBACKTRACEDEPTH 0#endif#endif
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。
1. 开源生态
2. 协作、人、软件
3. 评估模型