Boost logo

Boost-Commit :

From: phil_at_[hidden]
Date: 2008-05-19 06:46:46


Author: pbouchard
Date: 2008-05-19 06:46:45 EDT (Mon, 19 May 2008)
New Revision: 45539
URL: http://svn.boost.org/trac/boost/changeset/45539

Log:
Nedmalloc imported successfully.
Added:
   sandbox/shifted_ptr/boost/detail/local_pool.hpp (contents, props changed)
   sandbox/shifted_ptr/boost/detail/nedmalloc.c.h (contents, props changed)
   sandbox/shifted_ptr/libs/smart_ptr/example/local_pool_test1.cpp (contents, props changed)
   sandbox/shifted_ptr/libs/smart_ptr/example/local_pool_test2.cpp (contents, props changed)
Removed:
   sandbox/shifted_ptr/boost/detail/nedmalloc.c
   sandbox/shifted_ptr/boost/detail/tlh_pool.hpp
   sandbox/shifted_ptr/libs/smart_ptr/example/tlh_pool_test1.cpp
Text files modified:
   sandbox/shifted_ptr/boost/detail/malloc.c.h | 11 ++++++
   sandbox/shifted_ptr/boost/detail/nedmalloc.h | 12 ++++++++
   sandbox/shifted_ptr/boost/detail/sh_owned_base_nt.hpp | 60 ++++++++++------------------------------
   sandbox/shifted_ptr/boost/shifted_ptr.hpp | 10 +++---
   sandbox/shifted_ptr/libs/smart_ptr/example/shifted_ptr_test3.cpp | 4 --
   5 files changed, 42 insertions(+), 55 deletions(-)

Added: sandbox/shifted_ptr/boost/detail/local_pool.hpp
==============================================================================
--- (empty file)
+++ sandbox/shifted_ptr/boost/detail/local_pool.hpp 2008-05-19 06:46:45 EDT (Mon, 19 May 2008)
@@ -0,0 +1,79 @@
+/**
+ @file
+ Boost local_pool.hpp header file.
+
+ @author
+ Copyright (c) 2008 Phil Bouchard <phil_at_[hidden]>
+ 2005-2007 Niall Douglas <s_sourceforge_at_[hidden]>
+
+ @note
+ Distributed under the Boost Software License, Version 1.0.
+
+ See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt
+
+ See http://www.boost.org/libs/smart_ptr/doc/index.html for documentation.
+*/
+
+
+#ifndef BOOST_LOCAL_POOL_HPP
+#define BOOST_LOCAL_POOL_HPP
+
+#include <cstddef>
+
+#include <boost/config.hpp>
+#include <boost/pool/poolfwd.hpp>
+
+#include <boost/detail/nedmalloc.c.h>
+
+
+#ifdef BOOST_NO_STDC_NAMESPACE
+ namespace std { using ::malloc; using ::free; }
+#endif
+
+namespace boost {
+
+
+class local_pool
+{
+ public:
+ typedef size_t size_type;
+ typedef ptrdiff_t difference_type;
+
+
+ explicit local_pool(const size_type nrequested_size = 0, const size_type nnext_size = 32)
+ {
+ p = nedcreatepool(nrequested_size, 0);
+ }
+ ~local_pool()
+ {
+ neddestroypool(p);
+ }
+
+ bool release_memory();
+ bool purge_memory();
+ void * malloc(const size_type n)
+ {
+ return nedpmalloc(p, n);
+ }
+ void * ordered_malloc();
+ void * ordered_malloc(size_type n);
+ void free(void * const chunk)
+ {
+ nedpfree(p, chunk);
+ }
+ void ordered_free(void * const chunk);
+ void free(void * const chunks, const size_type n);
+ void ordered_free(void * const chunks, const size_type n);
+ bool is_from(void * const chunk) const
+ {
+ return nedpisfrom(p, chunk);
+ }
+
+ private:
+ nedpool * p;
+};
+
+} // namespace boost
+
+#endif

Modified: sandbox/shifted_ptr/boost/detail/malloc.c.h
==============================================================================
--- sandbox/shifted_ptr/boost/detail/malloc.c.h (original)
+++ sandbox/shifted_ptr/boost/detail/malloc.c.h 2008-05-19 06:46:45 EDT (Mon, 19 May 2008)
@@ -495,7 +495,9 @@
 #endif /* WIN32 */
 #ifdef WIN32
 #define WIN32_LEAN_AND_MEAN
+#ifndef _WIN32_WINNT
 #define _WIN32_WINNT 0x403
+#endif
 #include <windows.h>
 #define HAVE_MMAP 1
 #define HAVE_MORECORE 0
@@ -2496,7 +2498,14 @@
 
 #endif /* !ONLY_MSPACES */
 
-#define is_initialized(M) ((M)->top != 0)
+/*!
+ PAB:
+ - macro -> inline function
+*/
+inline bool is_initialized(mstate & m)
+{
+ return m->top != 0;
+}
 
 /* -------------------------- system alloc setup ------------------------- */
 

Deleted: sandbox/shifted_ptr/boost/detail/nedmalloc.c
==============================================================================
--- sandbox/shifted_ptr/boost/detail/nedmalloc.c 2008-05-19 06:46:45 EDT (Mon, 19 May 2008)
+++ (empty file)
@@ -1,943 +0,0 @@
-/* Alternative malloc implementation for multiple threads without
-lock contention based on dlmalloc. (C) 2005-2006 Niall Douglas
-
-Boost Software License - Version 1.0 - August 17th, 2003
-
-Permission is hereby granted, free of charge, to any person or organization
-obtaining a copy of the software and accompanying documentation covered by
-this license (the "Software") to use, reproduce, display, distribute,
-execute, and transmit the Software, and to prepare derivative works of the
-Software, and to permit third-parties to whom the Software is furnished to
-do so, all subject to the following:
-
-The copyright notices in the Software and this entire statement, including
-the above license grant, this restriction and the following disclaimer,
-must be included in all copies of the Software, in whole or in part, and
-all derivative works of the Software, unless such copies or derivative
-works are solely in the form of machine-executable object code generated by
-a source language processor.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
-SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
-FOR 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 OTHER
-DEALINGS IN THE SOFTWARE.
-*/
-
-#ifdef _MSC_VER
-/* Enable full aliasing on MSVC */
-/*#pragma optimize("a", on)*/
-#endif
-
-/*#define FULLSANITYCHECKS*/
-
-#include "nedmalloc.h"
-#define MSPACES 1
-#define ONLY_MSPACES 1
-#ifndef USE_LOCKS
- #define USE_LOCKS 1
-#endif
-#define FOOTERS 1 /* Need to enable footers so frees lock the right mspace */
-#undef DEBUG /* dlmalloc wants DEBUG either 0 or 1 */
-#ifdef _DEBUG
- #define DEBUG 1
-#else
- #define DEBUG 0
-#endif
-#ifdef NDEBUG /* Disable assert checking on release builds */
- #undef DEBUG
-#endif
-/* The default of 64Kb means we spend too much time kernel-side */
-#ifndef DEFAULT_GRANULARITY
-#define DEFAULT_GRANULARITY (1*1024*1024)
-#endif
-/*#define USE_SPIN_LOCKS 0*/
-
-
-/*#define FORCEINLINE*/
-#include "malloc.c.h"
-#ifdef NDEBUG /* Disable assert checking on release builds */
- #undef DEBUG
-#endif
-
-/* The maximum concurrent threads in a pool possible */
-#ifndef MAXTHREADSINPOOL
-#define MAXTHREADSINPOOL 16
-#endif
-/* The maximum number of threadcaches which can be allocated */
-#ifndef THREADCACHEMAXCACHES
-#define THREADCACHEMAXCACHES 256
-#endif
-/* The maximum size to be allocated from the thread cache */
-#ifndef THREADCACHEMAX
-#define THREADCACHEMAX 8192
-#endif
-#if 0
-/* The number of cache entries for finer grained bins. This is (topbitpos(THREADCACHEMAX)-4)*2 */
-#define THREADCACHEMAXBINS ((13-4)*2)
-#else
-/* The number of cache entries. This is (topbitpos(THREADCACHEMAX)-4) */
-#define THREADCACHEMAXBINS (13-4)
-#endif
-/* Point at which the free space in a thread cache is garbage collected */
-#ifndef THREADCACHEMAXFREESPACE
-#define THREADCACHEMAXFREESPACE (512*1024)
-#endif
-
-
-#ifdef WIN32
- #define TLSVAR DWORD
- #define TLSALLOC(k) (*(k)=TlsAlloc(), TLS_OUT_OF_INDEXES==*(k))
- #define TLSFREE(k) (!TlsFree(k))
- #define TLSGET(k) TlsGetValue(k)
- #define TLSSET(k, a) (!TlsSetValue(k, a))
- #ifdef DEBUG
-static LPVOID ChkedTlsGetValue(DWORD idx)
-{
- LPVOID ret=TlsGetValue(idx);
- assert(S_OK==GetLastError());
- return ret;
-}
- #undef TLSGET
- #define TLSGET(k) ChkedTlsGetValue(k)
- #endif
-#else
- #define TLSVAR pthread_key_t
- #define TLSALLOC(k) pthread_key_create(k, 0)
- #define TLSFREE(k) pthread_key_delete(k)
- #define TLSGET(k) pthread_getspecific(k)
- #define TLSSET(k, a) pthread_setspecific(k, a)
-#endif
-
-#if 0
-/* Only enable if testing with valgrind. Causes misoperation */
-#define mspace_malloc(p, s) malloc(s)
-#define mspace_realloc(p, m, s) realloc(m, s)
-#define mspace_calloc(p, n, s) calloc(n, s)
-#define mspace_free(p, m) free(m)
-#endif
-
-
-#if defined(__cplusplus)
-#if !defined(NO_NED_NAMESPACE)
-namespace nedalloc {
-#else
-extern "C" {
-#endif
-#endif
-
-size_t nedblksize(void *mem) THROWSPEC
-{
-#if 0
- /* Only enable if testing with valgrind. Causes misoperation */
- return THREADCACHEMAX;
-#else
- if(mem)
- {
- mchunkptr p=mem2chunk(mem);
- assert(cinuse(p)); /* If this fails, someone tried to free a block twice */
- if(cinuse(p))
- return chunksize(p)-overhead_for(p);
- }
- return 0;
-#endif
-}
-
-void nedsetvalue(void *v) THROWSPEC { nedpsetvalue(0, v); }
-void * nedmalloc(size_t size) THROWSPEC { return nedpmalloc(0, size); }
-void * nedcalloc(size_t no, size_t size) THROWSPEC { return nedpcalloc(0, no, size); }
-void * nedrealloc(void *mem, size_t size) THROWSPEC { return nedprealloc(0, mem, size); }
-void nedfree(void *mem) THROWSPEC { nedpfree(0, mem); }
-void * nedmemalign(size_t alignment, size_t bytes) THROWSPEC { return nedpmemalign(0, alignment, bytes); }
-#if !NO_MALLINFO
-struct mallinfo nedmallinfo(void) THROWSPEC { return nedpmallinfo(0); }
-#endif
-int nedmallopt(int parno, int value) THROWSPEC { return nedpmallopt(0, parno, value); }
-int nedmalloc_trim(size_t pad) THROWSPEC { return nedpmalloc_trim(0, pad); }
-void nedmalloc_stats() THROWSPEC { nedpmalloc_stats(0); }
-size_t nedmalloc_footprint() THROWSPEC { return nedpmalloc_footprint(0); }
-void **nedindependent_calloc(size_t elemsno, size_t elemsize, void **chunks) THROWSPEC { return nedpindependent_calloc(0, elemsno, elemsize, chunks); }
-void **nedindependent_comalloc(size_t elems, size_t *sizes, void **chunks) THROWSPEC { return nedpindependent_comalloc(0, elems, sizes, chunks); }
-
-struct threadcacheblk_t;
-typedef struct threadcacheblk_t threadcacheblk;
-struct threadcacheblk_t
-{ /* Keep less than 16 bytes on 32 bit systems and 32 bytes on 64 bit systems */
-#ifdef FULLSANITYCHECKS
- unsigned int magic;
-#endif
- unsigned int lastUsed, size;
- threadcacheblk *next, *prev;
-};
-typedef struct threadcache_t
-{
-#ifdef FULLSANITYCHECKS
- unsigned int magic1;
-#endif
- int mymspace; /* Last mspace entry this thread used */
- long threadid;
- unsigned int mallocs, frees, successes;
- size_t freeInCache; /* How much free space is stored in this cache */
- threadcacheblk *bins[(THREADCACHEMAXBINS+1)*2];
-#ifdef FULLSANITYCHECKS
- unsigned int magic2;
-#endif
-} threadcache;
-struct nedpool_t
-{
- MLOCK_T mutex;
- void *uservalue;
- int threads; /* Max entries in m to use */
- threadcache *caches[THREADCACHEMAXCACHES];
- TLSVAR mycache; /* Thread cache for this thread. 0 for unset, negative for use mspace-1 directly, otherwise is cache-1 */
- mstate m[MAXTHREADSINPOOL+1]; /* mspace entries for this pool */
-};
-static nedpool syspool;
-
-static FORCEINLINE unsigned int size2binidx(size_t _size) THROWSPEC
-{ /* 8=1000 16=10000 20=10100 24=11000 32=100000 48=110000 4096=1000000000000 */
- unsigned int topbit, size=(unsigned int)(_size>>4);
- /* 16=1 20=1 24=1 32=10 48=11 64=100 96=110 128=1000 4096=100000000 */
-
-#if defined(__GNUC__)
- topbit = sizeof(size)*__CHAR_BIT__ - 1 - __builtin_clz(size);
-#elif defined(_MSC_VER) && _MSC_VER>=1300
- {
- unsigned long bsrTopBit;
-
- _BitScanReverse(&bsrTopBit, size);
-
- topbit = bsrTopBit;
- }
-#else
-#if 0
- union {
- unsigned asInt[2];
- double asDouble;
- };
- int n;
-
- asDouble = (double)size + 0.5;
- topbit = (asInt[!FOX_BIGENDIAN] >> 20) - 1023;
-#else
- {
- unsigned int x=size;
- x = x | (x >> 1);
- x = x | (x >> 2);
- x = x | (x >> 4);
- x = x | (x >> 8);
- x = x | (x >>16);
- x = ~x;
- x = x - ((x >> 1) & 0x55555555);
- x = (x & 0x33333333) + ((x >> 2) & 0x33333333);
- x = (x + (x >> 4)) & 0x0F0F0F0F;
- x = x + (x << 8);
- x = x + (x << 16);
- topbit=31 - (x >> 24);
- }
-#endif
-#endif
- return topbit;
-}
-
-
-#ifdef FULLSANITYCHECKS
-static void tcsanitycheck(threadcacheblk **ptr) THROWSPEC
-{
- assert((ptr[0] && ptr[1]) || (!ptr[0] && !ptr[1]));
- if(ptr[0] && ptr[1])
- {
- assert(nedblksize(ptr[0])>=sizeof(threadcacheblk));
- assert(nedblksize(ptr[1])>=sizeof(threadcacheblk));
- assert(*(unsigned int *) "NEDN"==ptr[0]->magic);
- assert(*(unsigned int *) "NEDN"==ptr[1]->magic);
- assert(!ptr[0]->prev);
- assert(!ptr[1]->next);
- if(ptr[0]==ptr[1])
- {
- assert(!ptr[0]->next);
- assert(!ptr[1]->prev);
- }
- }
-}
-static void tcfullsanitycheck(threadcache *tc) THROWSPEC
-{
- threadcacheblk **tcbptr=tc->bins;
- int n;
- for(n=0; n<=THREADCACHEMAXBINS; n++, tcbptr+=2)
- {
- threadcacheblk *b, *ob=0;
- tcsanitycheck(tcbptr);
- for(b=tcbptr[0]; b; ob=b, b=b->next)
- {
- assert(*(unsigned int *) "NEDN"==b->magic);
- assert(!ob || ob->next==b);
- assert(!ob || b->prev==ob);
- }
- }
-}
-#endif
-
-static NOINLINE void RemoveCacheEntries(nedpool *p, threadcache *tc, unsigned int age) THROWSPEC
-{
-#ifdef FULLSANITYCHECKS
- tcfullsanitycheck(tc);
-#endif
- if(tc->freeInCache)
- {
- threadcacheblk **tcbptr=tc->bins;
- int n;
- for(n=0; n<=THREADCACHEMAXBINS; n++, tcbptr+=2)
- {
- threadcacheblk **tcb=tcbptr+1; /* come from oldest end of list */
- /*tcsanitycheck(tcbptr);*/
- for(; *tcb && tc->frees-(*tcb)->lastUsed>=age; )
- {
- threadcacheblk *f=*tcb;
- size_t blksize=f->size; /*nedblksize(f);*/
- assert(blksize<=nedblksize(f));
- assert(blksize);
-#ifdef FULLSANITYCHECKS
- assert(*(unsigned int *) "NEDN"==(*tcb)->magic);
-#endif
- *tcb=(*tcb)->prev;
- if(*tcb)
- (*tcb)->next=0;
- else
- *tcbptr=0;
- tc->freeInCache-=blksize;
- assert((long) tc->freeInCache>=0);
- mspace_free(0, f);
- /*tcsanitycheck(tcbptr);*/
- }
- }
- }
-#ifdef FULLSANITYCHECKS
- tcfullsanitycheck(tc);
-#endif
-}
-static void DestroyCaches(nedpool *p) THROWSPEC
-{
- if(p->caches)
- {
- threadcache *tc;
- int n;
- for(n=0; n<THREADCACHEMAXCACHES; n++)
- {
- if((tc=p->caches[n]))
- {
- tc->frees++;
- RemoveCacheEntries(p, tc, 0);
- assert(!tc->freeInCache);
- tc->mymspace=-1;
- tc->threadid=0;
- mspace_free(0, tc);
- p->caches[n]=0;
- }
- }
- }
-}
-
-static NOINLINE threadcache *AllocCache(nedpool *p) THROWSPEC
-{
- threadcache *tc=0;
- int n, end;
- ACQUIRE_LOCK(&p->mutex);
- for(n=0; n<THREADCACHEMAXCACHES && p->caches[n]; n++);
- if(THREADCACHEMAXCACHES==n)
- { /* List exhausted, so disable for this thread */
- RELEASE_LOCK(&p->mutex);
- return 0;
- }
- tc=p->caches[n]=(threadcache *) mspace_calloc(p->m[0], 1, sizeof(threadcache));
- if(!tc)
- {
- RELEASE_LOCK(&p->mutex);
- return 0;
- }
-#ifdef FULLSANITYCHECKS
- tc->magic1=*(unsigned int *)"NEDMALC1";
- tc->magic2=*(unsigned int *)"NEDMALC2";
-#endif
- tc->threadid=(long)(size_t)CURRENT_THREAD;
- for(end=0; p->m[end]; end++);
- tc->mymspace=tc->threadid % end;
- RELEASE_LOCK(&p->mutex);
- TLSSET(p->mycache, (void *)(size_t)(n+1));
- return tc;
-}
-
-static void *threadcache_malloc(nedpool *p, threadcache *tc, size_t *size) THROWSPEC
-{
- void *ret=0;
- unsigned int bestsize;
- unsigned int idx=size2binidx(*size);
- size_t blksize=0;
- threadcacheblk *blk, **binsptr;
-#ifdef FULLSANITYCHECKS
- tcfullsanitycheck(tc);
-#endif
- /* Calculate best fit bin size */
- bestsize=1<<(idx+4);
-#if 0
- /* Finer grained bin fit */
- idx<<=1;
- if(*size>bestsize)
- {
- idx++;
- bestsize+=bestsize>>1;
- }
- if(*size>bestsize)
- {
- idx++;
- bestsize=1<<(4+(idx>>1));
- }
-#else
- if(*size>bestsize)
- {
- idx++;
- bestsize<<=1;
- }
-#endif
- assert(bestsize>=*size);
- if(*size<bestsize) *size=bestsize;
- assert(*size<=THREADCACHEMAX);
- assert(idx<=THREADCACHEMAXBINS);
- binsptr=&tc->bins[idx*2];
- /* Try to match close, but move up a bin if necessary */
- blk=*binsptr;
- if(!blk || blk->size<*size)
- { /* Bump it up a bin */
- if(idx<THREADCACHEMAXBINS)
- {
- idx++;
- binsptr+=2;
- blk=*binsptr;
- }
- }
- if(blk)
- {
- blksize=blk->size; /*nedblksize(blk);*/
- assert(nedblksize(blk)>=blksize);
- assert(blksize>=*size);
- if(blk->next)
- blk->next->prev=0;
- *binsptr=blk->next;
- if(!*binsptr)
- binsptr[1]=0;
-#ifdef FULLSANITYCHECKS
- blk->magic=0;
-#endif
- assert(binsptr[0]!=blk && binsptr[1]!=blk);
- assert(nedblksize(blk)>=sizeof(threadcacheblk) && nedblksize(blk)<=THREADCACHEMAX+CHUNK_OVERHEAD);
- /*printf("malloc: %p, %p, %p, %lu\n", p, tc, blk, (long) size);*/
- ret=(void *) blk;
- }
- ++tc->mallocs;
- if(ret)
- {
- assert(blksize>=*size);
- ++tc->successes;
- tc->freeInCache-=blksize;
- assert((long) tc->freeInCache>=0);
- }
-#if defined(DEBUG) && 0
- if(!(tc->mallocs & 0xfff))
- {
- printf("*** threadcache=%u, mallocs=%u (%f), free=%u (%f), freeInCache=%u\n", (unsigned int) tc->threadid, tc->mallocs,
- (float) tc->successes/tc->mallocs, tc->frees, (float) tc->successes/tc->frees, (unsigned int) tc->freeInCache);
- }
-#endif
-#ifdef FULLSANITYCHECKS
- tcfullsanitycheck(tc);
-#endif
- return ret;
-}
-static NOINLINE void ReleaseFreeInCache(nedpool *p, threadcache *tc, int mymspace) THROWSPEC
-{
- unsigned int age=THREADCACHEMAXFREESPACE/8192;
- /*ACQUIRE_LOCK(&p->m[mymspace]->mutex);*/
- while(age && tc->freeInCache>=THREADCACHEMAXFREESPACE)
- {
- RemoveCacheEntries(p, tc, age);
- /*printf("*** Removing cache entries older than %u (%u)\n", age, (unsigned int) tc->freeInCache);*/
- age>>=1;
- }
- /*RELEASE_LOCK(&p->m[mymspace]->mutex);*/
-}
-static void threadcache_free(nedpool *p, threadcache *tc, int mymspace, void *mem, size_t size) THROWSPEC
-{
- unsigned int bestsize;
- unsigned int idx=size2binidx(size);
- threadcacheblk **binsptr, *tck=(threadcacheblk *) mem;
- assert(size>=sizeof(threadcacheblk) && size<=THREADCACHEMAX+CHUNK_OVERHEAD);
-#ifdef DEBUG
- { /* Make sure this is a valid memory block */
- mchunkptr p = mem2chunk(mem);
- mstate fm = get_mstate_for(p);
- if (!ok_magic(fm)) {
- USAGE_ERROR_ACTION(fm, p);
- return;
- }
- }
-#endif
-#ifdef FULLSANITYCHECKS
- tcfullsanitycheck(tc);
-#endif
- /* Calculate best fit bin size */
- bestsize=1<<(idx+4);
-#if 0
- /* Finer grained bin fit */
- idx<<=1;
- if(size>bestsize)
- {
- unsigned int biggerbestsize=bestsize+bestsize<<1;
- if(size>=biggerbestsize)
- {
- idx++;
- bestsize=biggerbestsize;
- }
- }
-#endif
- if(bestsize!=size) /* dlmalloc can round up, so we round down to preserve indexing */
- size=bestsize;
- binsptr=&tc->bins[idx*2];
- assert(idx<=THREADCACHEMAXBINS);
- if(tck==*binsptr)
- {
- fprintf(stderr, "Attempt to free already freed memory block %p - aborting!\n", tck);
- abort();
- }
-#ifdef FULLSANITYCHECKS
- tck->magic=*(unsigned int *) "NEDN";
-#endif
- tck->lastUsed=++tc->frees;
- tck->size=(unsigned int) size;
- tck->next=*binsptr;
- tck->prev=0;
- if(tck->next)
- tck->next->prev=tck;
- else
- binsptr[1]=tck;
- assert(!*binsptr || (*binsptr)->size==tck->size);
- *binsptr=tck;
- assert(tck==tc->bins[idx*2]);
- assert(tc->bins[idx*2+1]==tck || binsptr[0]->next->prev==tck);
- /*printf("free: %p, %p, %p, %lu\n", p, tc, mem, (long) size);*/
- tc->freeInCache+=size;
-#ifdef FULLSANITYCHECKS
- tcfullsanitycheck(tc);
-#endif
-#if 1
- if(tc->freeInCache>=THREADCACHEMAXFREESPACE)
- ReleaseFreeInCache(p, tc, mymspace);
-#endif
-}
-
-
-
-
-static NOINLINE int InitPool(nedpool *p, size_t capacity, int threads) THROWSPEC
-{ /* threads is -1 for system pool */
- ensure_initialization();
- ACQUIRE_MALLOC_GLOBAL_LOCK();
- if(p->threads) goto done;
- if(INITIAL_LOCK(&p->mutex)) goto err;
- if(TLSALLOC(&p->mycache)) goto err;
- if(!(p->m[0]=(mstate) create_mspace(capacity, 1))) goto err;
- p->m[0]->extp=p;
- p->threads=(threads<1 || threads>MAXTHREADSINPOOL) ? MAXTHREADSINPOOL : threads;
-done:
- RELEASE_MALLOC_GLOBAL_LOCK();
- return 1;
-err:
- if(threads<0)
- abort(); /* If you can't allocate for system pool, we're screwed */
- DestroyCaches(p);
- if(p->m[0])
- {
- destroy_mspace(p->m[0]);
- p->m[0]=0;
- }
- if(p->mycache)
- {
- TLSFREE(p->mycache);
- p->mycache=0;
- }
- RELEASE_MALLOC_GLOBAL_LOCK();
- return 0;
-}
-static NOINLINE mstate FindMSpace(nedpool *p, threadcache *tc, int *lastUsed, size_t size) THROWSPEC
-{ /* Gets called when thread's last used mspace is in use. The strategy
- is to run through the list of all available mspaces looking for an
- unlocked one and if we fail, we create a new one so long as we don't
- exceed p->threads */
- int n, end;
- for(n=end=*lastUsed+1; p->m[n]; end=++n)
- {
- if(TRY_LOCK(&p->m[n]->mutex)) goto found;
- }
- for(n=0; n<*lastUsed && p->m[n]; n++)
- {
- if(TRY_LOCK(&p->m[n]->mutex)) goto found;
- }
- if(end<p->threads)
- {
- mstate temp;
- if(!(temp=(mstate) create_mspace(size, 1)))
- goto badexit;
- /* Now we're ready to modify the lists, we lock */
- ACQUIRE_LOCK(&p->mutex);
- while(p->m[end] && end<p->threads)
- end++;
- if(end>=p->threads)
- { /* Drat, must destroy it now */
- RELEASE_LOCK(&p->mutex);
- destroy_mspace((mspace) temp);
- goto badexit;
- }
- /* We really want to make sure this goes into memory now but we
- have to be careful of breaking aliasing rules, so write it twice */
- *((volatile struct malloc_state **) &p->m[end])=p->m[end]=temp;
- ACQUIRE_LOCK(&p->m[end]->mutex);
- /*printf("Created mspace idx %d\n", end);*/
- RELEASE_LOCK(&p->mutex);
- n=end;
- goto found;
- }
- /* Let it lock on the last one it used */
-badexit:
- ACQUIRE_LOCK(&p->m[*lastUsed]->mutex);
- return p->m[*lastUsed];
-found:
- *lastUsed=n;
- if(tc)
- tc->mymspace=n;
- else
- {
- TLSSET(p->mycache, (void *)(size_t)(-(n+1)));
- }
- return p->m[n];
-}
-
-nedpool *nedcreatepool(size_t capacity, int threads) THROWSPEC
-{
- nedpool *ret;
- if(!(ret=(nedpool *) nedpcalloc(0, 1, sizeof(nedpool)))) return 0;
- if(!InitPool(ret, capacity, threads))
- {
- nedpfree(0, ret);
- return 0;
- }
- return ret;
-}
-void neddestroypool(nedpool *p) THROWSPEC
-{
- int n;
- ACQUIRE_LOCK(&p->mutex);
- DestroyCaches(p);
- for(n=0; p->m[n]; n++)
- {
- destroy_mspace(p->m[n]);
- p->m[n]=0;
- }
- RELEASE_LOCK(&p->mutex);
- TLSFREE(p->mycache);
- nedpfree(0, p);
-}
-
-void nedpsetvalue(nedpool *p, void *v) THROWSPEC
-{
- if(!p) { p=&syspool; if(!syspool.threads) InitPool(&syspool, 0, -1); }
- p->uservalue=v;
-}
-void *nedgetvalue(nedpool **p, void *mem) THROWSPEC
-{
- nedpool *np=0;
- mchunkptr mcp=mem2chunk(mem);
- mstate fm;
- if(!(is_aligned(chunk2mem(mcp))) && mcp->head != FENCEPOST_HEAD) return 0;
- if(!cinuse(mcp)) return 0;
- if(!next_pinuse(mcp)) return 0;
- if(!is_mmapped(mcp) && !pinuse(mcp))
- {
- if(next_chunk(prev_chunk(mcp))!=mcp) return 0;
- }
- fm=get_mstate_for(mcp);
- if(!ok_magic(fm)) return 0;
- if(!ok_address(fm, mcp)) return 0;
- if(!fm->extp) return 0;
- np=(nedpool *) fm->extp;
- if(p) *p=np;
- return np->uservalue;
-}
-
-void neddisablethreadcache(nedpool *p) THROWSPEC
-{
- int mycache;
- if(!p)
- {
- p=&syspool;
- if(!syspool.threads) InitPool(&syspool, 0, -1);
- }
- mycache=(int)(size_t) TLSGET(p->mycache);
- if(!mycache)
- { /* Set to mspace 0 */
- TLSSET(p->mycache, (void *)-1);
- }
- else if(mycache>0)
- { /* Set to last used mspace */
- threadcache *tc=p->caches[mycache-1];
-#if defined(DEBUG)
- printf("Threadcache utilisation: %lf%% in cache with %lf%% lost to other threads\n",
- 100.0*tc->successes/tc->mallocs, 100.0*((double) tc->mallocs-tc->frees)/tc->mallocs);
-#endif
- TLSSET(p->mycache, (void *)(size_t)(-tc->mymspace));
- tc->frees++;
- RemoveCacheEntries(p, tc, 0);
- assert(!tc->freeInCache);
- tc->mymspace=-1;
- tc->threadid=0;
- mspace_free(0, p->caches[mycache-1]);
- p->caches[mycache-1]=0;
- }
-}
-
-#define GETMSPACE(m,p,tc,ms,s,action) \
- do \
- { \
- mstate m = GetMSpace((p),(tc),(ms),(s)); \
- action; \
- RELEASE_LOCK(&m->mutex); \
- } while (0)
-
-static FORCEINLINE mstate GetMSpace(nedpool *p, threadcache *tc, int mymspace, size_t size) THROWSPEC
-{ /* Returns a locked and ready for use mspace */
- mstate m=p->m[mymspace];
- assert(m);
- if(!TRY_LOCK(&p->m[mymspace]->mutex)) m=FindMSpace(p, tc, &mymspace, size);\
- /*assert(IS_LOCKED(&p->m[mymspace]->mutex));*/
- return m;
-}
-static FORCEINLINE void GetThreadCache(nedpool **p, threadcache **tc, int *mymspace, size_t *size) THROWSPEC
-{
- int mycache;
- if(size && *size<sizeof(threadcacheblk)) *size=sizeof(threadcacheblk);
- if(!*p)
- {
- *p=&syspool;
- if(!syspool.threads) InitPool(&syspool, 0, -1);
- }
- mycache=(int)(size_t) TLSGET((*p)->mycache);
- if(mycache>0)
- {
- *tc=(*p)->caches[mycache-1];
- *mymspace=(*tc)->mymspace;
- }
- else if(!mycache)
- {
- *tc=AllocCache(*p);
- if(!*tc)
- { /* Disable */
- TLSSET((*p)->mycache, (void *)-1);
- *mymspace=0;
- }
- else
- *mymspace=(*tc)->mymspace;
- }
- else
- {
- *tc=0;
- *mymspace=-mycache-1;
- }
- assert(*mymspace>=0);
- assert((long)(size_t)CURRENT_THREAD==(*tc)->threadid);
-#ifdef FULLSANITYCHECKS
- if(*tc)
- {
- if(*(unsigned int *)"NEDMALC1"!=(*tc)->magic1 || *(unsigned int *)"NEDMALC2"!=(*tc)->magic2)
- {
- abort();
- }
- }
-#endif
-}
-
-void * nedpmalloc(nedpool *p, size_t size) THROWSPEC
-{
- void *ret=0;
- threadcache *tc;
- int mymspace;
- GetThreadCache(&p, &tc, &mymspace, &size);
-#if THREADCACHEMAX
- if(tc && size<=THREADCACHEMAX)
- { /* Use the thread cache */
- ret=threadcache_malloc(p, tc, &size);
- }
-#endif
- if(!ret)
- { /* Use this thread's mspace */
- GETMSPACE(m, p, tc, mymspace, size,
- ret=mspace_malloc(m, size));
- }
- return ret;
-}
-void * nedpcalloc(nedpool *p, size_t no, size_t size) THROWSPEC
-{
- size_t rsize=size*no;
- void *ret=0;
- threadcache *tc;
- int mymspace;
- GetThreadCache(&p, &tc, &mymspace, &rsize);
-#if THREADCACHEMAX
- if(tc && rsize<=THREADCACHEMAX)
- { /* Use the thread cache */
- if((ret=threadcache_malloc(p, tc, &rsize)))
- memset(ret, 0, rsize);
- }
-#endif
- if(!ret)
- { /* Use this thread's mspace */
- GETMSPACE(m, p, tc, mymspace, rsize,
- ret=mspace_calloc(m, 1, rsize));
- }
- return ret;
-}
-void * nedprealloc(nedpool *p, void *mem, size_t size) THROWSPEC
-{
- void *ret=0;
- threadcache *tc;
- int mymspace;
- if(!mem) return nedpmalloc(p, size);
- GetThreadCache(&p, &tc, &mymspace, &size);
-#if THREADCACHEMAX
- if(tc && size && size<=THREADCACHEMAX)
- { /* Use the thread cache */
- size_t memsize=nedblksize(mem);
- assert(memsize);
- if((ret=threadcache_malloc(p, tc, &size)))
- {
- memcpy(ret, mem, memsize<size ? memsize : size);
- if(memsize<=THREADCACHEMAX)
- threadcache_free(p, tc, mymspace, mem, memsize);
- else
- mspace_free(0, mem);
- }
- }
-#endif
- if(!ret)
- { /* Reallocs always happen in the mspace they happened in, so skip
- locking the preferred mspace for this thread */
- ret=mspace_realloc(0, mem, size);
- }
- return ret;
-}
-void nedpfree(nedpool *p, void *mem) THROWSPEC
-{ /* Frees always happen in the mspace they happened in, so skip
- locking the preferred mspace for this thread */
- threadcache *tc;
- int mymspace;
- size_t memsize;
- assert(mem);
- GetThreadCache(&p, &tc, &mymspace, 0);
-#if THREADCACHEMAX
- memsize=nedblksize(mem);
- assert(memsize);
- if(mem && tc && memsize<=(THREADCACHEMAX+CHUNK_OVERHEAD))
- threadcache_free(p, tc, mymspace, mem, memsize);
- else
-#endif
- mspace_free(0, mem);
-}
-void * nedpmemalign(nedpool *p, size_t alignment, size_t bytes) THROWSPEC
-{
- void *ret;
- threadcache *tc;
- int mymspace;
- GetThreadCache(&p, &tc, &mymspace, &bytes);
- { /* Use this thread's mspace */
- GETMSPACE(m, p, tc, mymspace, bytes,
- ret=mspace_memalign(m, alignment, bytes));
- }
- return ret;
-}
-#if !NO_MALLINFO
-struct mallinfo nedpmallinfo(nedpool *p) THROWSPEC
-{
- int n;
- struct mallinfo ret={0};
- if(!p) { p=&syspool; if(!syspool.threads) InitPool(&syspool, 0, -1); }
- for(n=0; p->m[n]; n++)
- {
- struct mallinfo t=mspace_mallinfo(p->m[n]);
- ret.arena+=t.arena;
- ret.ordblks+=t.ordblks;
- ret.hblkhd+=t.hblkhd;
- ret.usmblks+=t.usmblks;
- ret.uordblks+=t.uordblks;
- ret.fordblks+=t.fordblks;
- ret.keepcost+=t.keepcost;
- }
- return ret;
-}
-#endif
-int nedpmallopt(nedpool *p, int parno, int value) THROWSPEC
-{
- return mspace_mallopt(parno, value);
-}
-int nedpmalloc_trim(nedpool *p, size_t pad) THROWSPEC
-{
- int n, ret=0;
- if(!p) { p=&syspool; if(!syspool.threads) InitPool(&syspool, 0, -1); }
- for(n=0; p->m[n]; n++)
- {
- ret+=mspace_trim(p->m[n], pad);
- }
- return ret;
-}
-void nedpmalloc_stats(nedpool *p) THROWSPEC
-{
- int n;
- if(!p) { p=&syspool; if(!syspool.threads) InitPool(&syspool, 0, -1); }
- for(n=0; p->m[n]; n++)
- {
- mspace_malloc_stats(p->m[n]);
- }
-}
-size_t nedpmalloc_footprint(nedpool *p) THROWSPEC
-{
- size_t ret=0;
- int n;
- if(!p) { p=&syspool; if(!syspool.threads) InitPool(&syspool, 0, -1); }
- for(n=0; p->m[n]; n++)
- {
- ret+=mspace_footprint(p->m[n]);
- }
- return ret;
-}
-void **nedpindependent_calloc(nedpool *p, size_t elemsno, size_t elemsize, void **chunks) THROWSPEC
-{
- void **ret;
- threadcache *tc;
- int mymspace;
- GetThreadCache(&p, &tc, &mymspace, &elemsize);
- GETMSPACE(m, p, tc, mymspace, elemsno*elemsize,
- ret=mspace_independent_calloc(m, elemsno, elemsize, chunks));
- return ret;
-}
-void **nedpindependent_comalloc(nedpool *p, size_t elems, size_t *sizes, void **chunks) THROWSPEC
-{
- void **ret;
- threadcache *tc;
- int mymspace;
- GetThreadCache(&p, &tc, &mymspace, 0);
- GETMSPACE(m, p, tc, mymspace, 0,
- ret=mspace_independent_comalloc(m, elems, sizes, chunks));
- return ret;
-}
-
-#if defined(__cplusplus)
-}
-#endif

Added: sandbox/shifted_ptr/boost/detail/nedmalloc.c.h
==============================================================================
--- (empty file)
+++ sandbox/shifted_ptr/boost/detail/nedmalloc.c.h 2008-05-19 06:46:45 EDT (Mon, 19 May 2008)
@@ -0,0 +1,960 @@
+/* Alternative malloc implementation for multiple threads without
+lock contention based on dlmalloc. (C) 2005-2006 Niall Douglas
+
+Boost Software License - Version 1.0 - August 17th, 2003
+
+Permission is hereby granted, free of charge, to any person or organization
+obtaining a copy of the software and accompanying documentation covered by
+this license (the "Software") to use, reproduce, display, distribute,
+execute, and transmit the Software, and to prepare derivative works of the
+Software, and to permit third-parties to whom the Software is furnished to
+do so, all subject to the following:
+
+The copyright notices in the Software and this entire statement, including
+the above license grant, this restriction and the following disclaimer,
+must be included in all copies of the Software, in whole or in part, and
+all derivative works of the Software, unless such copies or derivative
+works are solely in the form of machine-executable object code generated by
+a source language processor.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+FOR 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 OTHER
+DEALINGS IN THE SOFTWARE.
+*/
+
+#ifdef _MSC_VER
+/* Enable full aliasing on MSVC */
+/*#pragma optimize("a", on)*/
+#endif
+
+/*#define FULLSANITYCHECKS*/
+
+#include "nedmalloc.h"
+#define MSPACES 1
+#define ONLY_MSPACES 1
+#ifndef USE_LOCKS
+ #define USE_LOCKS 1
+#endif
+#define FOOTERS 1 /* Need to enable footers so frees lock the right mspace */
+#undef DEBUG /* dlmalloc wants DEBUG either 0 or 1 */
+#ifdef _DEBUG
+ #define DEBUG 1
+#else
+ #define DEBUG 0
+#endif
+#ifdef NDEBUG /* Disable assert checking on release builds */
+ #undef DEBUG
+#endif
+/* The default of 64Kb means we spend too much time kernel-side */
+#ifndef DEFAULT_GRANULARITY
+#define DEFAULT_GRANULARITY (1*1024*1024)
+#endif
+/*#define USE_SPIN_LOCKS 0*/
+
+
+/*#define FORCEINLINE*/
+#include "malloc.c.h"
+#ifdef NDEBUG /* Disable assert checking on release builds */
+ #undef DEBUG
+#endif
+
+/* The maximum concurrent threads in a pool possible */
+#ifndef MAXTHREADSINPOOL
+#define MAXTHREADSINPOOL 16
+#endif
+/* The maximum number of threadcaches which can be allocated */
+#ifndef THREADCACHEMAXCACHES
+#define THREADCACHEMAXCACHES 256
+#endif
+/* The maximum size to be allocated from the thread cache */
+#ifndef THREADCACHEMAX
+#define THREADCACHEMAX 8192
+#endif
+#if 0
+/* The number of cache entries for finer grained bins. This is (topbitpos(THREADCACHEMAX)-4)*2 */
+#define THREADCACHEMAXBINS ((13-4)*2)
+#else
+/* The number of cache entries. This is (topbitpos(THREADCACHEMAX)-4) */
+#define THREADCACHEMAXBINS (13-4)
+#endif
+/* Point at which the free space in a thread cache is garbage collected */
+#ifndef THREADCACHEMAXFREESPACE
+#define THREADCACHEMAXFREESPACE (512*1024)
+#endif
+
+
+#ifdef WIN32
+ #define TLSVAR DWORD
+ #define TLSALLOC(k) (*(k)=TlsAlloc(), TLS_OUT_OF_INDEXES==*(k))
+ #define TLSFREE(k) (!TlsFree(k))
+ #define TLSGET(k) TlsGetValue(k)
+ #define TLSSET(k, a) (!TlsSetValue(k, a))
+ #ifdef DEBUG
+static LPVOID ChkedTlsGetValue(DWORD idx)
+{
+ LPVOID ret=TlsGetValue(idx);
+ assert(S_OK==GetLastError());
+ return ret;
+}
+ #undef TLSGET
+ #define TLSGET(k) ChkedTlsGetValue(k)
+ #endif
+#else
+ #define TLSVAR pthread_key_t
+ #define TLSALLOC(k) pthread_key_create(k, 0)
+ #define TLSFREE(k) pthread_key_delete(k)
+ #define TLSGET(k) pthread_getspecific(k)
+ #define TLSSET(k, a) pthread_setspecific(k, a)
+#endif
+
+#if 0
+/* Only enable if testing with valgrind. Causes misoperation */
+#define mspace_malloc(p, s) malloc(s)
+#define mspace_realloc(p, m, s) realloc(m, s)
+#define mspace_calloc(p, n, s) calloc(n, s)
+#define mspace_free(p, m) free(m)
+#endif
+
+
+#if defined(__cplusplus)
+#if !defined(NO_NED_NAMESPACE)
+namespace nedalloc {
+#else
+extern "C" {
+#endif
+#endif
+
+size_t nedblksize(void *mem) THROWSPEC
+{
+#if 0
+ /* Only enable if testing with valgrind. Causes misoperation */
+ return THREADCACHEMAX;
+#else
+ if(mem)
+ {
+ mchunkptr p=mem2chunk(mem);
+ assert(cinuse(p)); /* If this fails, someone tried to free a block twice */
+ if(cinuse(p))
+ return chunksize(p)-overhead_for(p);
+ }
+ return 0;
+#endif
+}
+
+void nedsetvalue(void *v) THROWSPEC { nedpsetvalue(0, v); }
+void * nedmalloc(size_t size) THROWSPEC { return nedpmalloc(0, size); }
+void * nedcalloc(size_t no, size_t size) THROWSPEC { return nedpcalloc(0, no, size); }
+void * nedrealloc(void *mem, size_t size) THROWSPEC { return nedprealloc(0, mem, size); }
+void nedfree(void *mem) THROWSPEC { nedpfree(0, mem); }
+void * nedmemalign(size_t alignment, size_t bytes) THROWSPEC { return nedpmemalign(0, alignment, bytes); }
+#if !NO_MALLINFO
+struct mallinfo nedmallinfo(void) THROWSPEC { return nedpmallinfo(0); }
+#endif
+int nedmallopt(int parno, int value) THROWSPEC { return nedpmallopt(0, parno, value); }
+int nedmalloc_trim(size_t pad) THROWSPEC { return nedpmalloc_trim(0, pad); }
+void nedmalloc_stats() THROWSPEC { nedpmalloc_stats(0); }
+size_t nedmalloc_footprint() THROWSPEC { return nedpmalloc_footprint(0); }
+void **nedindependent_calloc(size_t elemsno, size_t elemsize, void **chunks) THROWSPEC { return nedpindependent_calloc(0, elemsno, elemsize, chunks); }
+void **nedindependent_comalloc(size_t elems, size_t *sizes, void **chunks) THROWSPEC { return nedpindependent_comalloc(0, elems, sizes, chunks); }
+
+struct threadcacheblk_t;
+typedef struct threadcacheblk_t threadcacheblk;
+struct threadcacheblk_t
+{ /* Keep less than 16 bytes on 32 bit systems and 32 bytes on 64 bit systems */
+#ifdef FULLSANITYCHECKS
+ unsigned int magic;
+#endif
+ unsigned int lastUsed, size;
+ threadcacheblk *next, *prev;
+};
+typedef struct threadcache_t
+{
+#ifdef FULLSANITYCHECKS
+ unsigned int magic1;
+#endif
+ int mymspace; /* Last mspace entry this thread used */
+ long threadid;
+ unsigned int mallocs, frees, successes;
+ size_t freeInCache; /* How much free space is stored in this cache */
+ threadcacheblk *bins[(THREADCACHEMAXBINS+1)*2];
+#ifdef FULLSANITYCHECKS
+ unsigned int magic2;
+#endif
+} threadcache;
+struct nedpool_t
+{
+ MLOCK_T mutex;
+ void *uservalue;
+ int threads; /* Max entries in m to use */
+ threadcache *caches[THREADCACHEMAXCACHES];
+ TLSVAR mycache; /* Thread cache for this thread. 0 for unset, negative for use mspace-1 directly, otherwise is cache-1 */
+ mstate m[MAXTHREADSINPOOL+1]; /* mspace entries for this pool */
+};
+static nedpool syspool;
+
+static FORCEINLINE unsigned int size2binidx(size_t _size) THROWSPEC
+{ /* 8=1000 16=10000 20=10100 24=11000 32=100000 48=110000 4096=1000000000000 */
+ unsigned int topbit, size=(unsigned int)(_size>>4);
+ /* 16=1 20=1 24=1 32=10 48=11 64=100 96=110 128=1000 4096=100000000 */
+
+#if defined(__GNUC__)
+ topbit = sizeof(size)*__CHAR_BIT__ - 1 - __builtin_clz(size);
+#elif defined(_MSC_VER) && _MSC_VER>=1300
+ {
+ unsigned long bsrTopBit;
+
+ _BitScanReverse(&bsrTopBit, size);
+
+ topbit = bsrTopBit;
+ }
+#else
+#if 0
+ union {
+ unsigned asInt[2];
+ double asDouble;
+ };
+ int n;
+
+ asDouble = (double)size + 0.5;
+ topbit = (asInt[!FOX_BIGENDIAN] >> 20) - 1023;
+#else
+ {
+ unsigned int x=size;
+ x = x | (x >> 1);
+ x = x | (x >> 2);
+ x = x | (x >> 4);
+ x = x | (x >> 8);
+ x = x | (x >>16);
+ x = ~x;
+ x = x - ((x >> 1) & 0x55555555);
+ x = (x & 0x33333333) + ((x >> 2) & 0x33333333);
+ x = (x + (x >> 4)) & 0x0F0F0F0F;
+ x = x + (x << 8);
+ x = x + (x << 16);
+ topbit=31 - (x >> 24);
+ }
+#endif
+#endif
+ return topbit;
+}
+
+
+#ifdef FULLSANITYCHECKS
+static void tcsanitycheck(threadcacheblk **ptr) THROWSPEC
+{
+ assert((ptr[0] && ptr[1]) || (!ptr[0] && !ptr[1]));
+ if(ptr[0] && ptr[1])
+ {
+ assert(nedblksize(ptr[0])>=sizeof(threadcacheblk));
+ assert(nedblksize(ptr[1])>=sizeof(threadcacheblk));
+ assert(*(unsigned int *) "NEDN"==ptr[0]->magic);
+ assert(*(unsigned int *) "NEDN"==ptr[1]->magic);
+ assert(!ptr[0]->prev);
+ assert(!ptr[1]->next);
+ if(ptr[0]==ptr[1])
+ {
+ assert(!ptr[0]->next);
+ assert(!ptr[1]->prev);
+ }
+ }
+}
+static void tcfullsanitycheck(threadcache *tc) THROWSPEC
+{
+ threadcacheblk **tcbptr=tc->bins;
+ int n;
+ for(n=0; n<=THREADCACHEMAXBINS; n++, tcbptr+=2)
+ {
+ threadcacheblk *b, *ob=0;
+ tcsanitycheck(tcbptr);
+ for(b=tcbptr[0]; b; ob=b, b=b->next)
+ {
+ assert(*(unsigned int *) "NEDN"==b->magic);
+ assert(!ob || ob->next==b);
+ assert(!ob || b->prev==ob);
+ }
+ }
+}
+#endif
+
+static NOINLINE void RemoveCacheEntries(nedpool *p, threadcache *tc, unsigned int age) THROWSPEC
+{
+#ifdef FULLSANITYCHECKS
+ tcfullsanitycheck(tc);
+#endif
+ if(tc->freeInCache)
+ {
+ threadcacheblk **tcbptr=tc->bins;
+ int n;
+ for(n=0; n<=THREADCACHEMAXBINS; n++, tcbptr+=2)
+ {
+ threadcacheblk **tcb=tcbptr+1; /* come from oldest end of list */
+ /*tcsanitycheck(tcbptr);*/
+ for(; *tcb && tc->frees-(*tcb)->lastUsed>=age; )
+ {
+ threadcacheblk *f=*tcb;
+ size_t blksize=f->size; /*nedblksize(f);*/
+ assert(blksize<=nedblksize(f));
+ assert(blksize);
+#ifdef FULLSANITYCHECKS
+ assert(*(unsigned int *) "NEDN"==(*tcb)->magic);
+#endif
+ *tcb=(*tcb)->prev;
+ if(*tcb)
+ (*tcb)->next=0;
+ else
+ *tcbptr=0;
+ tc->freeInCache-=blksize;
+ assert((long) tc->freeInCache>=0);
+ mspace_free(0, f);
+ /*tcsanitycheck(tcbptr);*/
+ }
+ }
+ }
+#ifdef FULLSANITYCHECKS
+ tcfullsanitycheck(tc);
+#endif
+}
+static void DestroyCaches(nedpool *p) THROWSPEC
+{
+ if(p->caches)
+ {
+ threadcache *tc;
+ int n;
+ for(n=0; n<THREADCACHEMAXCACHES; n++)
+ {
+ if((tc=p->caches[n]))
+ {
+ tc->frees++;
+ RemoveCacheEntries(p, tc, 0);
+ assert(!tc->freeInCache);
+ tc->mymspace=-1;
+ tc->threadid=0;
+ mspace_free(0, tc);
+ p->caches[n]=0;
+ }
+ }
+ }
+}
+
+static NOINLINE threadcache *AllocCache(nedpool *p) THROWSPEC
+{
+ threadcache *tc=0;
+ int n, end;
+ ACQUIRE_LOCK(&p->mutex);
+ for(n=0; n<THREADCACHEMAXCACHES && p->caches[n]; n++);
+ if(THREADCACHEMAXCACHES==n)
+ { /* List exhausted, so disable for this thread */
+ RELEASE_LOCK(&p->mutex);
+ return 0;
+ }
+ tc=p->caches[n]=(threadcache *) mspace_calloc(p->m[0], 1, sizeof(threadcache));
+ if(!tc)
+ {
+ RELEASE_LOCK(&p->mutex);
+ return 0;
+ }
+#ifdef FULLSANITYCHECKS
+ tc->magic1=*(unsigned int *)"NEDMALC1";
+ tc->magic2=*(unsigned int *)"NEDMALC2";
+#endif
+ tc->threadid=(long)(size_t)CURRENT_THREAD;
+ for(end=0; p->m[end]; end++);
+ tc->mymspace=tc->threadid % end;
+ RELEASE_LOCK(&p->mutex);
+ TLSSET(p->mycache, (void *)(size_t)(n+1));
+ return tc;
+}
+
+static void *threadcache_malloc(nedpool *p, threadcache *tc, size_t *size) THROWSPEC
+{
+ void *ret=0;
+ unsigned int bestsize;
+ unsigned int idx=size2binidx(*size);
+ size_t blksize=0;
+ threadcacheblk *blk, **binsptr;
+#ifdef FULLSANITYCHECKS
+ tcfullsanitycheck(tc);
+#endif
+ /* Calculate best fit bin size */
+ bestsize=1<<(idx+4);
+#if 0
+ /* Finer grained bin fit */
+ idx<<=1;
+ if(*size>bestsize)
+ {
+ idx++;
+ bestsize+=bestsize>>1;
+ }
+ if(*size>bestsize)
+ {
+ idx++;
+ bestsize=1<<(4+(idx>>1));
+ }
+#else
+ if(*size>bestsize)
+ {
+ idx++;
+ bestsize<<=1;
+ }
+#endif
+ assert(bestsize>=*size);
+ if(*size<bestsize) *size=bestsize;
+ assert(*size<=THREADCACHEMAX);
+ assert(idx<=THREADCACHEMAXBINS);
+ binsptr=&tc->bins[idx*2];
+ /* Try to match close, but move up a bin if necessary */
+ blk=*binsptr;
+ if(!blk || blk->size<*size)
+ { /* Bump it up a bin */
+ if(idx<THREADCACHEMAXBINS)
+ {
+ idx++;
+ binsptr+=2;
+ blk=*binsptr;
+ }
+ }
+ if(blk)
+ {
+ blksize=blk->size; /*nedblksize(blk);*/
+ assert(nedblksize(blk)>=blksize);
+ assert(blksize>=*size);
+ if(blk->next)
+ blk->next->prev=0;
+ *binsptr=blk->next;
+ if(!*binsptr)
+ binsptr[1]=0;
+#ifdef FULLSANITYCHECKS
+ blk->magic=0;
+#endif
+ assert(binsptr[0]!=blk && binsptr[1]!=blk);
+ assert(nedblksize(blk)>=sizeof(threadcacheblk) && nedblksize(blk)<=THREADCACHEMAX+CHUNK_OVERHEAD);
+ /*printf("malloc: %p, %p, %p, %lu\n", p, tc, blk, (long) size);*/
+ ret=(void *) blk;
+ }
+ ++tc->mallocs;
+ if(ret)
+ {
+ assert(blksize>=*size);
+ ++tc->successes;
+ tc->freeInCache-=blksize;
+ assert((long) tc->freeInCache>=0);
+ }
+#if defined(DEBUG) && 0
+ if(!(tc->mallocs & 0xfff))
+ {
+ printf("*** threadcache=%u, mallocs=%u (%f), free=%u (%f), freeInCache=%u\n", (unsigned int) tc->threadid, tc->mallocs,
+ (float) tc->successes/tc->mallocs, tc->frees, (float) tc->successes/tc->frees, (unsigned int) tc->freeInCache);
+ }
+#endif
+#ifdef FULLSANITYCHECKS
+ tcfullsanitycheck(tc);
+#endif
+ return ret;
+}
+static NOINLINE void ReleaseFreeInCache(nedpool *p, threadcache *tc, int mymspace) THROWSPEC
+{
+ unsigned int age=THREADCACHEMAXFREESPACE/8192;
+ /*ACQUIRE_LOCK(&p->m[mymspace]->mutex);*/
+ while(age && tc->freeInCache>=THREADCACHEMAXFREESPACE)
+ {
+ RemoveCacheEntries(p, tc, age);
+ /*printf("*** Removing cache entries older than %u (%u)\n", age, (unsigned int) tc->freeInCache);*/
+ age>>=1;
+ }
+ /*RELEASE_LOCK(&p->m[mymspace]->mutex);*/
+}
+static void threadcache_free(nedpool *p, threadcache *tc, int mymspace, void *mem, size_t size) THROWSPEC
+{
+ unsigned int bestsize;
+ unsigned int idx=size2binidx(size);
+ threadcacheblk **binsptr, *tck=(threadcacheblk *) mem;
+ assert(size>=sizeof(threadcacheblk) && size<=THREADCACHEMAX+CHUNK_OVERHEAD);
+#ifdef DEBUG
+ { /* Make sure this is a valid memory block */
+ mchunkptr p = mem2chunk(mem);
+ mstate fm = get_mstate_for(p);
+ if (!ok_magic(fm)) {
+ USAGE_ERROR_ACTION(fm, p);
+ return;
+ }
+ }
+#endif
+#ifdef FULLSANITYCHECKS
+ tcfullsanitycheck(tc);
+#endif
+ /* Calculate best fit bin size */
+ bestsize=1<<(idx+4);
+#if 0
+ /* Finer grained bin fit */
+ idx<<=1;
+ if(size>bestsize)
+ {
+ unsigned int biggerbestsize=bestsize+bestsize<<1;
+ if(size>=biggerbestsize)
+ {
+ idx++;
+ bestsize=biggerbestsize;
+ }
+ }
+#endif
+ if(bestsize!=size) /* dlmalloc can round up, so we round down to preserve indexing */
+ size=bestsize;
+ binsptr=&tc->bins[idx*2];
+ assert(idx<=THREADCACHEMAXBINS);
+ if(tck==*binsptr)
+ {
+ fprintf(stderr, "Attempt to free already freed memory block %p - aborting!\n", tck);
+ abort();
+ }
+#ifdef FULLSANITYCHECKS
+ tck->magic=*(unsigned int *) "NEDN";
+#endif
+ tck->lastUsed=++tc->frees;
+ tck->size=(unsigned int) size;
+ tck->next=*binsptr;
+ tck->prev=0;
+ if(tck->next)
+ tck->next->prev=tck;
+ else
+ binsptr[1]=tck;
+ assert(!*binsptr || (*binsptr)->size==tck->size);
+ *binsptr=tck;
+ assert(tck==tc->bins[idx*2]);
+ assert(tc->bins[idx*2+1]==tck || binsptr[0]->next->prev==tck);
+ /*printf("free: %p, %p, %p, %lu\n", p, tc, mem, (long) size);*/
+ tc->freeInCache+=size;
+#ifdef FULLSANITYCHECKS
+ tcfullsanitycheck(tc);
+#endif
+#if 1
+ if(tc->freeInCache>=THREADCACHEMAXFREESPACE)
+ ReleaseFreeInCache(p, tc, mymspace);
+#endif
+}
+
+
+
+
+static NOINLINE int InitPool(nedpool *p, size_t capacity, int threads) THROWSPEC
+{ /* threads is -1 for system pool */
+ ensure_initialization();
+ ACQUIRE_MALLOC_GLOBAL_LOCK();
+ if(p->threads) goto done;
+ if(INITIAL_LOCK(&p->mutex)) goto err;
+ if(TLSALLOC(&p->mycache)) goto err;
+ if(!(p->m[0]=(mstate) create_mspace(capacity, 1))) goto err;
+ p->m[0]->extp=p;
+ p->threads=(threads<1 || threads>MAXTHREADSINPOOL) ? MAXTHREADSINPOOL : threads;
+done:
+ RELEASE_MALLOC_GLOBAL_LOCK();
+ return 1;
+err:
+ if(threads<0)
+ abort(); /* If you can't allocate for system pool, we're screwed */
+ DestroyCaches(p);
+ if(p->m[0])
+ {
+ destroy_mspace(p->m[0]);
+ p->m[0]=0;
+ }
+ if(p->mycache)
+ {
+ TLSFREE(p->mycache);
+ p->mycache=0;
+ }
+ RELEASE_MALLOC_GLOBAL_LOCK();
+ return 0;
+}
+static NOINLINE mstate FindMSpace(nedpool *p, threadcache *tc, int *lastUsed, size_t size) THROWSPEC
+{ /* Gets called when thread's last used mspace is in use. The strategy
+ is to run through the list of all available mspaces looking for an
+ unlocked one and if we fail, we create a new one so long as we don't
+ exceed p->threads */
+ int n, end;
+ for(n=end=*lastUsed+1; p->m[n]; end=++n)
+ {
+ if(TRY_LOCK(&p->m[n]->mutex)) goto found;
+ }
+ for(n=0; n<*lastUsed && p->m[n]; n++)
+ {
+ if(TRY_LOCK(&p->m[n]->mutex)) goto found;
+ }
+ if(end<p->threads)
+ {
+ mstate temp;
+ if(!(temp=(mstate) create_mspace(size, 1)))
+ goto badexit;
+ /* Now we're ready to modify the lists, we lock */
+ ACQUIRE_LOCK(&p->mutex);
+ while(p->m[end] && end<p->threads)
+ end++;
+ if(end>=p->threads)
+ { /* Drat, must destroy it now */
+ RELEASE_LOCK(&p->mutex);
+ destroy_mspace((mspace) temp);
+ goto badexit;
+ }
+ /* We really want to make sure this goes into memory now but we
+ have to be careful of breaking aliasing rules, so write it twice */
+ *((volatile struct malloc_state **) &p->m[end])=p->m[end]=temp;
+ ACQUIRE_LOCK(&p->m[end]->mutex);
+ /*printf("Created mspace idx %d\n", end);*/
+ RELEASE_LOCK(&p->mutex);
+ n=end;
+ goto found;
+ }
+ /* Let it lock on the last one it used */
+badexit:
+ ACQUIRE_LOCK(&p->m[*lastUsed]->mutex);
+ return p->m[*lastUsed];
+found:
+ *lastUsed=n;
+ if(tc)
+ tc->mymspace=n;
+ else
+ {
+ TLSSET(p->mycache, (void *)(size_t)(-(n+1)));
+ }
+ return p->m[n];
+}
+
+nedpool *nedcreatepool(size_t capacity, int threads) THROWSPEC
+{
+ nedpool *ret;
+ if(!(ret=(nedpool *) nedpcalloc(0, 1, sizeof(nedpool)))) return 0;
+ if(!InitPool(ret, capacity, threads))
+ {
+ nedpfree(0, ret);
+ return 0;
+ }
+ return ret;
+}
+void neddestroypool(nedpool *p) THROWSPEC
+{
+ int n;
+ ACQUIRE_LOCK(&p->mutex);
+ DestroyCaches(p);
+ for(n=0; p->m[n]; n++)
+ {
+ destroy_mspace(p->m[n]);
+ p->m[n]=0;
+ }
+ RELEASE_LOCK(&p->mutex);
+ TLSFREE(p->mycache);
+ nedpfree(0, p);
+}
+
+void nedpsetvalue(nedpool *p, void *v) THROWSPEC
+{
+ if(!p) { p=&syspool; if(!syspool.threads) InitPool(&syspool, 0, -1); }
+ p->uservalue=v;
+}
+void *nedgetvalue(nedpool **p, void *mem) THROWSPEC
+{
+ nedpool *np=0;
+ mchunkptr mcp=mem2chunk(mem);
+ mstate fm;
+ if(!(is_aligned(chunk2mem(mcp))) && mcp->head != FENCEPOST_HEAD) return 0;
+ if(!cinuse(mcp)) return 0;
+ if(!next_pinuse(mcp)) return 0;
+ if(!is_mmapped(mcp) && !pinuse(mcp))
+ {
+ if(next_chunk(prev_chunk(mcp))!=mcp) return 0;
+ }
+ fm=get_mstate_for(mcp);
+ if(!ok_magic(fm)) return 0;
+ if(!ok_address(fm, mcp)) return 0;
+ if(!fm->extp) return 0;
+ np=(nedpool *) fm->extp;
+ if(p) *p=np;
+ return np->uservalue;
+}
+
+void neddisablethreadcache(nedpool *p) THROWSPEC
+{
+ int mycache;
+ if(!p)
+ {
+ p=&syspool;
+ if(!syspool.threads) InitPool(&syspool, 0, -1);
+ }
+ mycache=(int)(size_t) TLSGET(p->mycache);
+ if(!mycache)
+ { /* Set to mspace 0 */
+ TLSSET(p->mycache, (void *)-1);
+ }
+ else if(mycache>0)
+ { /* Set to last used mspace */
+ threadcache *tc=p->caches[mycache-1];
+#if defined(DEBUG)
+ printf("Threadcache utilisation: %lf%% in cache with %lf%% lost to other threads\n",
+ 100.0*tc->successes/tc->mallocs, 100.0*((double) tc->mallocs-tc->frees)/tc->mallocs);
+#endif
+ TLSSET(p->mycache, (void *)(size_t)(-tc->mymspace));
+ tc->frees++;
+ RemoveCacheEntries(p, tc, 0);
+ assert(!tc->freeInCache);
+ tc->mymspace=-1;
+ tc->threadid=0;
+ mspace_free(0, p->caches[mycache-1]);
+ p->caches[mycache-1]=0;
+ }
+}
+
+#define GETMSPACE(m,p,tc,ms,s,action) \
+ do \
+ { \
+ mstate m = GetMSpace((p),(tc),(ms),(s)); \
+ action; \
+ RELEASE_LOCK(&m->mutex); \
+ } while (0)
+
+static FORCEINLINE mstate GetMSpace(nedpool *p, threadcache *tc, int mymspace, size_t size) THROWSPEC
+{ /* Returns a locked and ready for use mspace */
+ mstate m=p->m[mymspace];
+ assert(m);
+ if(!TRY_LOCK(&p->m[mymspace]->mutex)) m=FindMSpace(p, tc, &mymspace, size);\
+ /*assert(IS_LOCKED(&p->m[mymspace]->mutex));*/
+ return m;
+}
+static FORCEINLINE void GetThreadCache(nedpool **p, threadcache **tc, int *mymspace, size_t *size) THROWSPEC
+{
+ int mycache;
+ if(size && *size<sizeof(threadcacheblk)) *size=sizeof(threadcacheblk);
+ if(!*p)
+ {
+ *p=&syspool;
+ if(!syspool.threads) InitPool(&syspool, 0, -1);
+ }
+ mycache=(int)(size_t) TLSGET((*p)->mycache);
+ if(mycache>0)
+ {
+ *tc=(*p)->caches[mycache-1];
+ *mymspace=(*tc)->mymspace;
+ }
+ else if(!mycache)
+ {
+ *tc=AllocCache(*p);
+ if(!*tc)
+ { /* Disable */
+ TLSSET((*p)->mycache, (void *)-1);
+ *mymspace=0;
+ }
+ else
+ *mymspace=(*tc)->mymspace;
+ }
+ else
+ {
+ *tc=0;
+ *mymspace=-mycache-1;
+ }
+ assert(*mymspace>=0);
+ assert((long)(size_t)CURRENT_THREAD==(*tc)->threadid);
+#ifdef FULLSANITYCHECKS
+ if(*tc)
+ {
+ if(*(unsigned int *)"NEDMALC1"!=(*tc)->magic1 || *(unsigned int *)"NEDMALC2"!=(*tc)->magic2)
+ {
+ abort();
+ }
+ }
+#endif
+}
+
+void * nedpmalloc(nedpool *p, size_t size) THROWSPEC
+{
+ void *ret=0;
+ threadcache *tc;
+ int mymspace;
+ GetThreadCache(&p, &tc, &mymspace, &size);
+#if THREADCACHEMAX
+ if(tc && size<=THREADCACHEMAX)
+ { /* Use the thread cache */
+ ret=threadcache_malloc(p, tc, &size);
+ }
+#endif
+ if(!ret)
+ { /* Use this thread's mspace */
+ GETMSPACE(m, p, tc, mymspace, size,
+ ret=mspace_malloc(m, size));
+ }
+ return ret;
+}
+void * nedpcalloc(nedpool *p, size_t no, size_t size) THROWSPEC
+{
+ size_t rsize=size*no;
+ void *ret=0;
+ threadcache *tc;
+ int mymspace;
+ GetThreadCache(&p, &tc, &mymspace, &rsize);
+#if THREADCACHEMAX
+ if(tc && rsize<=THREADCACHEMAX)
+ { /* Use the thread cache */
+ if((ret=threadcache_malloc(p, tc, &rsize)))
+ memset(ret, 0, rsize);
+ }
+#endif
+ if(!ret)
+ { /* Use this thread's mspace */
+ GETMSPACE(m, p, tc, mymspace, rsize,
+ ret=mspace_calloc(m, 1, rsize));
+ }
+ return ret;
+}
+void * nedprealloc(nedpool *p, void *mem, size_t size) THROWSPEC
+{
+ void *ret=0;
+ threadcache *tc;
+ int mymspace;
+ if(!mem) return nedpmalloc(p, size);
+ GetThreadCache(&p, &tc, &mymspace, &size);
+#if THREADCACHEMAX
+ if(tc && size && size<=THREADCACHEMAX)
+ { /* Use the thread cache */
+ size_t memsize=nedblksize(mem);
+ assert(memsize);
+ if((ret=threadcache_malloc(p, tc, &size)))
+ {
+ memcpy(ret, mem, memsize<size ? memsize : size);
+ if(memsize<=THREADCACHEMAX)
+ threadcache_free(p, tc, mymspace, mem, memsize);
+ else
+ mspace_free(0, mem);
+ }
+ }
+#endif
+ if(!ret)
+ { /* Reallocs always happen in the mspace they happened in, so skip
+ locking the preferred mspace for this thread */
+ ret=mspace_realloc(0, mem, size);
+ }
+ return ret;
+}
+void nedpfree(nedpool *p, void *mem) THROWSPEC
+{ /* Frees always happen in the mspace they happened in, so skip
+ locking the preferred mspace for this thread */
+ threadcache *tc;
+ int mymspace;
+ size_t memsize;
+ assert(mem);
+ GetThreadCache(&p, &tc, &mymspace, 0);
+#if THREADCACHEMAX
+ memsize=nedblksize(mem);
+ assert(memsize);
+ if(mem && tc && memsize<=(THREADCACHEMAX+CHUNK_OVERHEAD))
+ threadcache_free(p, tc, mymspace, mem, memsize);
+ else
+#endif
+ mspace_free(0, mem);
+}
+void * nedpmemalign(nedpool *p, size_t alignment, size_t bytes) THROWSPEC
+{
+ void *ret;
+ threadcache *tc;
+ int mymspace;
+ GetThreadCache(&p, &tc, &mymspace, &bytes);
+ { /* Use this thread's mspace */
+ GETMSPACE(m, p, tc, mymspace, bytes,
+ ret=mspace_memalign(m, alignment, bytes));
+ }
+ return ret;
+}
+#if !NO_MALLINFO
+struct mallinfo nedpmallinfo(nedpool *p) THROWSPEC
+{
+ int n;
+ struct mallinfo ret={0};
+ if(!p) { p=&syspool; if(!syspool.threads) InitPool(&syspool, 0, -1); }
+ for(n=0; p->m[n]; n++)
+ {
+ struct mallinfo t=mspace_mallinfo(p->m[n]);
+ ret.arena+=t.arena;
+ ret.ordblks+=t.ordblks;
+ ret.hblkhd+=t.hblkhd;
+ ret.usmblks+=t.usmblks;
+ ret.uordblks+=t.uordblks;
+ ret.fordblks+=t.fordblks;
+ ret.keepcost+=t.keepcost;
+ }
+ return ret;
+}
+#endif
+int nedpmallopt(nedpool *p, int parno, int value) THROWSPEC
+{
+ return mspace_mallopt(parno, value);
+}
+int nedpmalloc_trim(nedpool *p, size_t pad) THROWSPEC
+{
+ int n, ret=0;
+ if(!p) { p=&syspool; if(!syspool.threads) InitPool(&syspool, 0, -1); }
+ for(n=0; p->m[n]; n++)
+ {
+ ret+=mspace_trim(p->m[n], pad);
+ }
+ return ret;
+}
+void nedpmalloc_stats(nedpool *p) THROWSPEC
+{
+ int n;
+ if(!p) { p=&syspool; if(!syspool.threads) InitPool(&syspool, 0, -1); }
+ for(n=0; p->m[n]; n++)
+ {
+ mspace_malloc_stats(p->m[n]);
+ }
+}
+size_t nedpmalloc_footprint(nedpool *p) THROWSPEC
+{
+ size_t ret=0;
+ int n;
+ if(!p) { p=&syspool; if(!syspool.threads) InitPool(&syspool, 0, -1); }
+ for(n=0; p->m[n]; n++)
+ {
+ ret+=mspace_footprint(p->m[n]);
+ }
+ return ret;
+}
+void **nedpindependent_calloc(nedpool *p, size_t elemsno, size_t elemsize, void **chunks) THROWSPEC
+{
+ void **ret;
+ threadcache *tc;
+ int mymspace;
+ GetThreadCache(&p, &tc, &mymspace, &elemsize);
+ GETMSPACE(m, p, tc, mymspace, elemsno*elemsize,
+ ret=mspace_independent_calloc(m, elemsno, elemsize, chunks));
+ return ret;
+}
+void **nedpindependent_comalloc(nedpool *p, size_t elems, size_t *sizes, void **chunks) THROWSPEC
+{
+ void **ret;
+ threadcache *tc;
+ int mymspace;
+ GetThreadCache(&p, &tc, &mymspace, 0);
+ GETMSPACE(m, p, tc, mymspace, 0,
+ ret=mspace_independent_comalloc(m, elems, sizes, chunks));
+ return ret;
+}
+
+/*!
+ PAB:
+ - Boost.Pool import
+*/
+bool nedpisfrom(nedpool *p, void *mem) THROWSPEC
+{
+ size_t ret=0;
+ int n;
+ if(!p) { p=&syspool; if(!syspool.threads) InitPool(&syspool, 0, -1); }
+ for(n=0; p->m[n]; n++)
+ {
+ if (segment_holding(p->m[n], (char *)mem))
+ return true;
+ }
+ return false;
+}
+
+#if defined(__cplusplus)
+}
+#endif

Modified: sandbox/shifted_ptr/boost/detail/nedmalloc.h
==============================================================================
--- sandbox/shifted_ptr/boost/detail/nedmalloc.h (original)
+++ sandbox/shifted_ptr/boost/detail/nedmalloc.h 2008-05-19 06:46:45 EDT (Mon, 19 May 2008)
@@ -47,8 +47,14 @@
 
 */
 
+/*!
+ PAB:
+ - C++ fix
+*/
+#define NDEBUG
 #define NO_NED_NAMESPACE
 
+
 #include <stddef.h> /* for size_t */
 
 #ifndef EXTSPEC
@@ -172,6 +178,12 @@
 EXTSPEC MALLOCATTR void **nedpindependent_calloc(nedpool *p, size_t elemsno, size_t elemsize, void **chunks) THROWSPEC;
 EXTSPEC MALLOCATTR void **nedpindependent_comalloc(nedpool *p, size_t elems, size_t *sizes, void **chunks) THROWSPEC;
 
+/*!
+ PAB:
+ - Boost.Pool import
+*/
+EXTSPEC bool nedpisfrom(nedpool *p, void *mem) THROWSPEC;
+
 #if defined(__cplusplus)
 }
 #endif

Modified: sandbox/shifted_ptr/boost/detail/sh_owned_base_nt.hpp
==============================================================================
--- sandbox/shifted_ptr/boost/detail/sh_owned_base_nt.hpp (original)
+++ sandbox/shifted_ptr/boost/detail/sh_owned_base_nt.hpp 2008-05-19 06:46:45 EDT (Mon, 19 May 2008)
@@ -38,6 +38,7 @@
 #include <boost/detail/intrusive_stack.hpp>
 #include <boost/detail/sh_utility.h>
 #include <boost/detail/sp_counted_base_nt.hpp>
+#include <boost/detail/local_pool.hpp>
 
 
 namespace boost
@@ -66,51 +67,6 @@
 
 
 /**
- Segment boundaries.
-*/
-
-struct segment : std::pair<const void *, const void *>
-{
- typedef std::pair<const void *, const void *> base;
-
- segment(const void * p = (const void *)(std::numeric_limits<unsigned>::max)(), const void * q = (const void *)(std::numeric_limits<unsigned>::min)()) : base((const void *)(p), (const void *)(q))
- {
- }
-
- void include(const void * p)
- {
- if (p < static_cast<const void *>(first)) first = p;
- if (p > static_cast<const void *>(second)) second = p;
- }
-
- bool contains(const void * p)
- {
- return ! (static_cast<char const *>(p) < first || static_cast<char const *>(p) > second);
- }
-};
-
-
-/**
- Auto stack boundaries.
-*/
-
-struct stack_segment : segment
-{
- bool contains(const void * p)
- {
-#if defined(__GNUC__)
- include(__builtin_frame_address(0));
- include(__builtin_frame_address(3));
-#else
-#error Compiler not yet supported.
-#endif
-
- return segment::contains(p);
- }
-} stack_;
-
-
-/**
         Root class of all pointees.
 */
 
@@ -133,6 +89,8 @@
         intrusive_list::node * set_tag() { return & set_tag_; }
         intrusive_list::node * init_tag() { return & init_tag_; }
 
+ static local_pool pool_;
+
 #ifndef BOOST_SH_DISABLE_THREADS
         static thread_specific_stack last;
 #else
@@ -141,6 +99,8 @@
 };
 
 
+local_pool owned_base::pool_;
+
 #ifndef BOOST_SH_DISABLE_THREADS
 thread_specific_stack owned_base::last;
 #else
@@ -184,6 +144,16 @@
                         
                         operator owned<data_type> * () const { return p_; }
                 };
+
+ void * operator new (size_t s)
+ {
+ return pool_.malloc(s);
+ }
+
+ void operator delete (void * p)
+ {
+ pool_.free(p);
+ }
 
         private:
                 template <typename U>

Deleted: sandbox/shifted_ptr/boost/detail/tlh_pool.hpp
==============================================================================
--- sandbox/shifted_ptr/boost/detail/tlh_pool.hpp 2008-05-19 06:46:45 EDT (Mon, 19 May 2008)
+++ (empty file)
@@ -1,64 +0,0 @@
-/**
- @file
- Boost tlh_pool.hpp header file.
-
- @author
- Copyright (c) 2008 Phil Bouchard <phil_at_[hidden]>.
-
- @note
- Distributed under the Boost Software License, Version 1.0.
-
- See accompanying file LICENSE_1_0.txt or copy at
- http://www.boost.org/LICENSE_1_0.txt
-
- See http://www.boost.org/libs/smart_ptr/doc/index.html for documentation.
-*/
-
-
-#ifndef BOOST_TLH_POOL_HPP
-#define BOOST_TLH_POOL_HPP
-
-#include <cstddef>
-
-#include <boost/config.hpp>
-#include <boost/pool/poolfwd.hpp>
-
-#include "nedmalloc.c"
-
-
-#ifdef BOOST_NO_STDC_NAMESPACE
- namespace std { using ::malloc; using ::free; }
-#endif
-
-namespace boost {
-
-
-class tlh_pool
-{
- public:
- typedef size_t size_type;
- typedef ptrdiff_t difference_type;
-
- private:
- BOOST_STATIC_CONSTANT(unsigned, min_alloc_size =
- (::boost::details::pool::ct_lcm<sizeof(void *), sizeof(size_type)>::value) );
-
- public:
- explicit tlh_pool(const size_type nrequested_size, const size_type nnext_size = 32);
- ~pool();
-
- bool release_memory();
- bool purge_memory();
- void * malloc();
- void * ordered_malloc();
- void * ordered_malloc(size_type n);
- void free(void * const chunk);
- void ordered_free(void * const chunk);
- void free(void * const chunks, const size_type n);
- void ordered_free(void * const chunks, const size_type n);
- bool is_from(void * const chunk) const;
-};
-
-} // namespace boost
-
-#endif

Modified: sandbox/shifted_ptr/boost/shifted_ptr.hpp
==============================================================================
--- sandbox/shifted_ptr/boost/shifted_ptr.hpp (original)
+++ sandbox/shifted_ptr/boost/shifted_ptr.hpp 2008-05-19 06:46:45 EDT (Mon, 19 May 2008)
@@ -149,7 +149,7 @@
 
                 shifted_ptr() : ps_(0)
                 {
- if (stack_.contains(this))
+ if (! owned_base::pool_.is_from(this))
                                 ps_ = new set();
                         else
                                 owned_base::last->top()->ptrs()->push(& pn_);
@@ -158,7 +158,7 @@
                 template <typename V>
                         shifted_ptr(owned<V> * p) : U<T>(p)
                         {
- if (stack_.contains(this))
+ if (! owned_base::pool_.is_from(this))
                                 {
                                         ps_ = new set();
 
@@ -174,7 +174,7 @@
                 template <typename V>
                         shifted_ptr(shifted_ptr<V> const & p) : U<T>(p)
                         {
- if (stack_.contains(this))
+ if (! owned_base::pool_.is_from(this))
                                         ps_ = new set();
                                 else
                                         owned_base::last->top()->ptrs()->push(& pn_);
@@ -184,7 +184,7 @@
 
                         shifted_ptr(shifted_ptr<T> const & p) : U<T>(p)
                         {
- if (stack_.contains(this))
+ if (! owned_base::pool_.is_from(this))
                                         ps_ = new set();
                                 else
                                         owned_base::last->top()->ptrs()->push(& pn_);
@@ -235,7 +235,7 @@
         private:
                 void release(bool d = false)
                 {
- if (stack_.contains(this))
+ if (! owned_base::pool_.is_from(this))
                         {
                                 if (ps_->release())
                                 {

Added: sandbox/shifted_ptr/libs/smart_ptr/example/local_pool_test1.cpp
==============================================================================
--- (empty file)
+++ sandbox/shifted_ptr/libs/smart_ptr/example/local_pool_test1.cpp 2008-05-19 06:46:45 EDT (Mon, 19 May 2008)
@@ -0,0 +1,360 @@
+/* test.c
+An example of how to use nedalloc
+(C) 2005-2007 Niall Douglas
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <boost/detail/nedmalloc.c.h>
+
+#define THREADS 5
+#define RECORDS (100000/THREADS)
+#define TORTURETEST 1
+
+static int whichmalloc;
+static int doRealloc;
+static struct threadstuff_t
+{
+ int ops;
+ unsigned int *toalloc;
+ void **allocs;
+ char cachesync1[128];
+ int done;
+ char cachesync2[128];
+} threadstuff[THREADS];
+
+static void threadcode(int);
+
+#ifdef WIN32
+#include <winnt.h>
+
+static DWORD WINAPI _threadcode(LPVOID a)
+{
+ threadcode((int)(size_t) a);
+ return 0;
+}
+#define THREADVAR HANDLE
+#define THREADINIT(v, id) (*v=CreateThread(NULL, 0, _threadcode, (LPVOID)(size_t) id, 0, NULL))
+#define THREADSLEEP(v) SleepEx(v, FALSE)
+#define THREADWAIT(v) (WaitForSingleObject(v, INFINITE), 0)
+
+typedef unsigned __int64 usCount;
+static FORCEINLINE usCount GetUsCount()
+{
+ static LARGE_INTEGER ticksPerSec;
+ static double scalefactor;
+ LARGE_INTEGER val;
+ if(!scalefactor)
+ {
+ if(QueryPerformanceFrequency(&ticksPerSec))
+ scalefactor=ticksPerSec.QuadPart/1000000000000.0;
+ else
+ scalefactor=1;
+ }
+ if(!QueryPerformanceCounter(&val))
+ return (usCount) GetTickCount() * 1000000000;
+ return (usCount) (val.QuadPart/scalefactor);
+}
+
+static HANDLE win32heap;
+static void *win32malloc(size_t size)
+{
+ return HeapAlloc(win32heap, 0, size);
+}
+static void *win32realloc(void *p, size_t size)
+{
+ return HeapReAlloc(win32heap, 0, p, size);
+}
+static void win32free(void *mem)
+{
+ HeapFree(win32heap, 0, mem);
+}
+
+static void *(*const mallocs[])(size_t size)={ malloc, nedmalloc, win32malloc };
+static void *(*const reallocs[])(void *p, size_t size)={ realloc, nedrealloc, win32realloc };
+static void (*const frees[])(void *mem)={ free, nedfree, win32free };
+#else
+static void *_threadcode(void *a)
+{
+ threadcode((int)(size_t) a);
+ return 0;
+}
+#define THREADVAR pthread_t
+#define THREADINIT(v, id) pthread_create(v, NULL, _threadcode, (void *)(size_t) id)
+#define THREADSLEEP(v) usleep(v*1000)
+#define THREADWAIT(v) pthread_join(v, NULL)
+
+typedef unsigned long long usCount;
+static FORCEINLINE usCount GetUsCount()
+{
+ struct timeval tv;
+ gettimeofday(&tv, 0);
+ return ((usCount) tv.tv_sec*1000000000000LL)+tv.tv_usec*1000000LL;
+}
+
+static void *(*const mallocs[])(size_t size)={ malloc, nedmalloc };
+static void *(*const reallocs[])(void *p, size_t size)={ realloc, nedrealloc };
+static void (*const frees[])(void *mem)={ free, nedfree };
+#endif
+static usCount times[THREADS];
+
+
+static FORCEINLINE unsigned int myrandom(unsigned int *seed)
+{
+ *seed=1664525UL*(*seed)+1013904223UL;
+ return *seed;
+}
+
+static void threadcode(int threadidx)
+{
+ int n;
+ unsigned int *toallocptr=threadstuff[threadidx].toalloc;
+ void **allocptr=threadstuff[threadidx].allocs;
+ unsigned int seed=threadidx;
+ usCount start;
+ threadstuff[threadidx].done=0;
+ /*neddisablethreadcache(0);*/
+ THREADSLEEP(100);
+ start=GetUsCount();
+#ifdef TORTURETEST
+ /* A randomised malloc/realloc/free test (torture test) */
+ for(n=0; n<RECORDS*100; n++)
+ {
+ unsigned int r=myrandom(&seed), i;
+ i=(int)(r % RECORDS);
+ if(!allocptr[i])
+ {
+ allocptr[i]=mallocs[whichmalloc](r & 0x1FFF);
+ threadstuff[threadidx].ops++;
+ }
+ else if(r & (1<<31))
+ {
+ allocptr[i]=reallocs[whichmalloc](allocptr[i], r & 0x1FFF);
+ threadstuff[threadidx].ops++;
+ }
+ else
+ {
+ frees[whichmalloc](allocptr[i]);
+ allocptr[i]=0;
+ }
+ }
+ for(n=0; n<RECORDS; n++)
+ {
+ if(allocptr[n])
+ {
+ frees[whichmalloc](allocptr[n]);
+ allocptr[n]=0;
+ }
+ }
+#else
+ /* A simple stack which allocates and deallocates off the top (speed test) */
+ for(n=0; n<RECORDS;)
+ {
+#if 1
+ r=myrandom(&seed);
+ if(allocptr>threadstuff[threadidx].allocs && (r & 65535)<32760) /*<32760)*/
+ { /* free */
+ --toallocptr;
+ --allocptr;
+ --n;
+ frees[whichmalloc](*allocptr);
+ *allocptr=0;
+ }
+ else
+#endif
+ {
+ if(doRealloc && allocptr>threadstuff[threadidx].allocs && (r & 1))
+ {
+ allocptr[-1]=reallocs[whichmalloc](allocptr[-1], *toallocptr);
+ }
+ else
+ {
+ allocptr[0]=mallocs[whichmalloc](*toallocptr);
+ allocptr++;
+ }
+ n++;
+ toallocptr++;
+ threadstuff[threadidx].ops++;
+ }
+ }
+ while(allocptr>threadstuff[threadidx].allocs)
+ {
+ frees[whichmalloc](*--allocptr);
+ }
+#endif
+ times[threadidx]+=GetUsCount()-start;
+ neddisablethreadcache(0);
+ threadstuff[threadidx].done=1;
+}
+
+static double runtest()
+{
+ unsigned int seed=1;
+ int n, i;
+ double opspersec=0;
+ THREADVAR threads[THREADS];
+ for(n=0; n<THREADS; n++)
+ {
+ unsigned int *toallocptr;
+ int m;
+ threadstuff[n].ops=0;
+ times[n]=0;
+ threadstuff[n].toalloc=toallocptr=(unsigned int *)calloc(RECORDS, sizeof(unsigned int));
+ threadstuff[n].allocs=(void **)calloc(RECORDS, sizeof(void *));
+ for(m=0; m<RECORDS; m++)
+ {
+ unsigned int size=myrandom(&seed);
+ if(size<(1<<30))
+ { /* Make it two power multiple of less than 512 bytes to
+ model frequent C++ new's */
+ size=4<<(size & 7);
+ }
+ else
+ {
+ size&=0x3FFF; /* < 16Kb */
+ /*size&=0x1FFF;*/ /* < 8Kb */
+ /*size=(1<<6)<<(size & 7);*/ /* < 8Kb */
+ }
+ *toallocptr++=size;
+ }
+ }
+#ifdef TORTURETEST
+ for(n=0; n<THREADS; n++)
+ {
+ THREADINIT(&threads[n], n);
+ }
+ for(i=0; i<32; i++)
+ {
+ int found=-1;
+ do
+ {
+ for(n=0; n<THREADS; n++)
+ {
+ THREADSLEEP(100);
+ if(threadstuff[n].done)
+ {
+ found=n;
+ break;
+ }
+ }
+ } while(found<0);
+ THREADWAIT(threads[found]);
+ threads[found]=0;
+ THREADINIT(&threads[found], found);
+ printf("Relaunched thread %d\n", found);
+ }
+ for(n=THREADS-1; n>=0; n--)
+ {
+ THREADWAIT(threads[n]);
+ threads[n]=0;
+ }
+#else
+#if 1
+ for(n=0; n<THREADS; n++)
+ {
+ THREADINIT(&threads[n], n);
+ }
+ for(n=THREADS-1; n>=0; n--)
+ {
+ THREADWAIT(threads[n]);
+ threads[n]=0;
+ }
+#else
+ /* Quick realloc() test */
+ doRealloc=1;
+ for(n=0; n<THREADS; n++)
+ {
+ THREADINIT(&threads[n], n);
+ }
+ for(n=THREADS-1; n>=0; n--)
+ {
+ THREADWAIT(threads[n]);
+ threads[n]=0;
+ }
+#endif
+#endif
+ {
+ usCount totaltime=0;
+ int totalops=0;
+ for(n=0; n<THREADS; n++)
+ {
+ totaltime+=times[n];
+ totalops+=threadstuff[n].ops;
+ }
+ opspersec=1000000000000.0*totalops/totaltime*THREADS;
+ printf("This allocator achieves %lfops/sec under %d threads\n", opspersec, THREADS);
+ }
+ for(n=THREADS-1; n>=0; n--)
+ {
+ free(threadstuff[n].allocs); threadstuff[n].allocs=0;
+ free(threadstuff[n].toalloc); threadstuff[n].toalloc=0;
+ }
+ return opspersec;
+}
+
+int main(void)
+{
+ double std=0, ned=0;
+
+#if 0
+ {
+ usCount start, end;
+ start=GetUsCount();
+ THREADSLEEP(5000);
+ end=GetUsCount();
+ printf("Wait was %lf\n", (end-start)/1000000000000.0);
+ }
+#endif
+#ifdef WIN32
+ { /* Force load of user32.dll so we can debug */
+ BOOL v;
+ SystemParametersInfo(SPI_GETBEEP, 0, &v, 0);
+ }
+#endif
+
+ if(0)
+ {
+ printf("\nTesting standard allocator with %d threads ...\n", THREADS);
+ std=runtest();
+ }
+ if(1)
+ {
+ printf("\nTesting nedmalloc with %d threads ...\n", THREADS);
+ whichmalloc=1;
+ ned=runtest();
+ }
+#ifdef WIN32
+/*
+ if(0)
+ {
+ ULONG data=2;
+ win32heap=HeapCreate(0, 0, 0);
+ HeapSetInformation(win32heap, HeapCompatibilityInformation, &data, sizeof(data));
+ HeapQueryInformation(win32heap, HeapCompatibilityInformation, &data, sizeof(data), NULL);
+ if(2!=data)
+ {
+ printf("The win32 low frag allocator won't work under a debugger!\n");
+ }
+ else
+ {
+ printf("Testing win32 low frag allocator with %d threads ...\n\n", THREADS);
+ whichmalloc=2;
+ runtest();
+ }
+ HeapDestroy(win32heap);
+ }
+*/
+#endif
+ if(std && ned)
+ { // ned should have more ops/sec
+ printf("\n\nnedmalloc allocator is %lf times faster than standard\n", ned/std);
+ }
+ printf("\nPress a key to trim\n");
+ getchar();
+ nedmalloc_trim(0);
+#ifdef _MSC_VER
+ printf("\nPress a key to end\n");
+ getchar();
+#endif
+ return 0;
+}

Added: sandbox/shifted_ptr/libs/smart_ptr/example/local_pool_test2.cpp
==============================================================================
--- (empty file)
+++ sandbox/shifted_ptr/libs/smart_ptr/example/local_pool_test2.cpp 2008-05-19 06:46:45 EDT (Mon, 19 May 2008)
@@ -0,0 +1,25 @@
+/**
+ @file
+ local_pool_test2.cpp.
+*/
+
+
+#include <iostream>
+
+#include <boost/detail/local_pool.hpp>
+
+using namespace std;
+using namespace boost;
+
+
+int main(void)
+{
+ local_pool pool[2];
+
+ void * p = pool[0].malloc(10);
+
+ cout << (pool[0].is_from(p) ? "true" : "false") << endl;
+ cout << (pool[1].is_from(p) ? "true" : "false") << endl;
+
+ return 0;
+}

Modified: sandbox/shifted_ptr/libs/smart_ptr/example/shifted_ptr_test3.cpp
==============================================================================
--- sandbox/shifted_ptr/libs/smart_ptr/example/shifted_ptr_test3.cpp (original)
+++ sandbox/shifted_ptr/libs/smart_ptr/example/shifted_ptr_test3.cpp 2008-05-19 06:46:45 EDT (Mon, 19 May 2008)
@@ -80,14 +80,12 @@
 };
 
 BOOST_AUTO_TEST_CASE(test_shifted_ptr) {
-/*
     count = 0;
     {
         shifted_ptr<vector> v = new_sh<vector>();
         v->elements.push_back(v);
     }
     BOOST_CHECK_EQUAL(count, 0);
-*/
 
     count = 0;
     {
@@ -115,7 +113,6 @@
         boost::mpl::for_each<boost::mpl::range_c<int, 1, 100> >(create_type());
     }
 
-/*
     count = 0;
     {
         shifted_ptr<vector> v = new_sh<vector>();
@@ -128,5 +125,4 @@
         v.elements.push_back(new_sh<vector>());
     }
     BOOST_CHECK_EQUAL(count, 0);
-*/
 }

Deleted: sandbox/shifted_ptr/libs/smart_ptr/example/tlh_pool_test1.cpp
==============================================================================
--- sandbox/shifted_ptr/libs/smart_ptr/example/tlh_pool_test1.cpp 2008-05-19 06:46:45 EDT (Mon, 19 May 2008)
+++ (empty file)
@@ -1,360 +0,0 @@
-/* test.c
-An example of how to use nedalloc
-(C) 2005-2007 Niall Douglas
-*/
-
-#include <stdio.h>
-#include <stdlib.h>
-#include "nedmalloc.c"
-
-#define THREADS 5
-#define RECORDS (100000/THREADS)
-#define TORTURETEST 1
-
-static int whichmalloc;
-static int doRealloc;
-static struct threadstuff_t
-{
- int ops;
- unsigned int *toalloc;
- void **allocs;
- char cachesync1[128];
- int done;
- char cachesync2[128];
-} threadstuff[THREADS];
-
-static void threadcode(int);
-
-#ifdef WIN32
-#include <winnt.h>
-
-static DWORD WINAPI _threadcode(LPVOID a)
-{
- threadcode((int)(size_t) a);
- return 0;
-}
-#define THREADVAR HANDLE
-#define THREADINIT(v, id) (*v=CreateThread(NULL, 0, _threadcode, (LPVOID)(size_t) id, 0, NULL))
-#define THREADSLEEP(v) SleepEx(v, FALSE)
-#define THREADWAIT(v) (WaitForSingleObject(v, INFINITE), 0)
-
-typedef unsigned __int64 usCount;
-static FORCEINLINE usCount GetUsCount()
-{
- static LARGE_INTEGER ticksPerSec;
- static double scalefactor;
- LARGE_INTEGER val;
- if(!scalefactor)
- {
- if(QueryPerformanceFrequency(&ticksPerSec))
- scalefactor=ticksPerSec.QuadPart/1000000000000.0;
- else
- scalefactor=1;
- }
- if(!QueryPerformanceCounter(&val))
- return (usCount) GetTickCount() * 1000000000;
- return (usCount) (val.QuadPart/scalefactor);
-}
-
-static HANDLE win32heap;
-static void *win32malloc(size_t size)
-{
- return HeapAlloc(win32heap, 0, size);
-}
-static void *win32realloc(void *p, size_t size)
-{
- return HeapReAlloc(win32heap, 0, p, size);
-}
-static void win32free(void *mem)
-{
- HeapFree(win32heap, 0, mem);
-}
-
-static void *(*const mallocs[])(size_t size)={ malloc, nedmalloc, win32malloc };
-static void *(*const reallocs[])(void *p, size_t size)={ realloc, nedrealloc, win32realloc };
-static void (*const frees[])(void *mem)={ free, nedfree, win32free };
-#else
-static void *_threadcode(void *a)
-{
- threadcode((int)(size_t) a);
- return 0;
-}
-#define THREADVAR pthread_t
-#define THREADINIT(v, id) pthread_create(v, NULL, _threadcode, (void *)(size_t) id)
-#define THREADSLEEP(v) usleep(v*1000)
-#define THREADWAIT(v) pthread_join(v, NULL)
-
-typedef unsigned long long usCount;
-static FORCEINLINE usCount GetUsCount()
-{
- struct timeval tv;
- gettimeofday(&tv, 0);
- return ((usCount) tv.tv_sec*1000000000000LL)+tv.tv_usec*1000000LL;
-}
-
-static void *(*const mallocs[])(size_t size)={ malloc, nedmalloc };
-static void *(*const reallocs[])(void *p, size_t size)={ realloc, nedrealloc };
-static void (*const frees[])(void *mem)={ free, nedfree };
-#endif
-static usCount times[THREADS];
-
-
-static FORCEINLINE unsigned int myrandom(unsigned int *seed)
-{
- *seed=1664525UL*(*seed)+1013904223UL;
- return *seed;
-}
-
-static void threadcode(int threadidx)
-{
- int n;
- unsigned int *toallocptr=threadstuff[threadidx].toalloc;
- void **allocptr=threadstuff[threadidx].allocs;
- unsigned int seed=threadidx;
- usCount start;
- threadstuff[threadidx].done=0;
- /*neddisablethreadcache(0);*/
- THREADSLEEP(100);
- start=GetUsCount();
-#ifdef TORTURETEST
- /* A randomised malloc/realloc/free test (torture test) */
- for(n=0; n<RECORDS*100; n++)
- {
- unsigned int r=myrandom(&seed), i;
- i=(int)(r % RECORDS);
- if(!allocptr[i])
- {
- allocptr[i]=mallocs[whichmalloc](r & 0x1FFF);
- threadstuff[threadidx].ops++;
- }
- else if(r & (1<<31))
- {
- allocptr[i]=reallocs[whichmalloc](allocptr[i], r & 0x1FFF);
- threadstuff[threadidx].ops++;
- }
- else
- {
- frees[whichmalloc](allocptr[i]);
- allocptr[i]=0;
- }
- }
- for(n=0; n<RECORDS; n++)
- {
- if(allocptr[n])
- {
- frees[whichmalloc](allocptr[n]);
- allocptr[n]=0;
- }
- }
-#else
- /* A simple stack which allocates and deallocates off the top (speed test) */
- for(n=0; n<RECORDS;)
- {
-#if 1
- r=myrandom(&seed);
- if(allocptr>threadstuff[threadidx].allocs && (r & 65535)<32760) /*<32760)*/
- { /* free */
- --toallocptr;
- --allocptr;
- --n;
- frees[whichmalloc](*allocptr);
- *allocptr=0;
- }
- else
-#endif
- {
- if(doRealloc && allocptr>threadstuff[threadidx].allocs && (r & 1))
- {
- allocptr[-1]=reallocs[whichmalloc](allocptr[-1], *toallocptr);
- }
- else
- {
- allocptr[0]=mallocs[whichmalloc](*toallocptr);
- allocptr++;
- }
- n++;
- toallocptr++;
- threadstuff[threadidx].ops++;
- }
- }
- while(allocptr>threadstuff[threadidx].allocs)
- {
- frees[whichmalloc](*--allocptr);
- }
-#endif
- times[threadidx]+=GetUsCount()-start;
- neddisablethreadcache(0);
- threadstuff[threadidx].done=1;
-}
-
-static double runtest()
-{
- unsigned int seed=1;
- int n, i;
- double opspersec=0;
- THREADVAR threads[THREADS];
- for(n=0; n<THREADS; n++)
- {
- unsigned int *toallocptr;
- int m;
- threadstuff[n].ops=0;
- times[n]=0;
- threadstuff[n].toalloc=toallocptr=(unsigned int *)calloc(RECORDS, sizeof(unsigned int));
- threadstuff[n].allocs=(void **)calloc(RECORDS, sizeof(void *));
- for(m=0; m<RECORDS; m++)
- {
- unsigned int size=myrandom(&seed);
- if(size<(1<<30))
- { /* Make it two power multiple of less than 512 bytes to
- model frequent C++ new's */
- size=4<<(size & 7);
- }
- else
- {
- size&=0x3FFF; /* < 16Kb */
- /*size&=0x1FFF;*/ /* < 8Kb */
- /*size=(1<<6)<<(size & 7);*/ /* < 8Kb */
- }
- *toallocptr++=size;
- }
- }
-#ifdef TORTURETEST
- for(n=0; n<THREADS; n++)
- {
- THREADINIT(&threads[n], n);
- }
- for(i=0; i<32; i++)
- {
- int found=-1;
- do
- {
- for(n=0; n<THREADS; n++)
- {
- THREADSLEEP(100);
- if(threadstuff[n].done)
- {
- found=n;
- break;
- }
- }
- } while(found<0);
- THREADWAIT(threads[found]);
- threads[found]=0;
- THREADINIT(&threads[found], found);
- printf("Relaunched thread %d\n", found);
- }
- for(n=THREADS-1; n>=0; n--)
- {
- THREADWAIT(threads[n]);
- threads[n]=0;
- }
-#else
-#if 1
- for(n=0; n<THREADS; n++)
- {
- THREADINIT(&threads[n], n);
- }
- for(n=THREADS-1; n>=0; n--)
- {
- THREADWAIT(threads[n]);
- threads[n]=0;
- }
-#else
- /* Quick realloc() test */
- doRealloc=1;
- for(n=0; n<THREADS; n++)
- {
- THREADINIT(&threads[n], n);
- }
- for(n=THREADS-1; n>=0; n--)
- {
- THREADWAIT(threads[n]);
- threads[n]=0;
- }
-#endif
-#endif
- {
- usCount totaltime=0;
- int totalops=0;
- for(n=0; n<THREADS; n++)
- {
- totaltime+=times[n];
- totalops+=threadstuff[n].ops;
- }
- opspersec=1000000000000.0*totalops/totaltime*THREADS;
- printf("This allocator achieves %lfops/sec under %d threads\n", opspersec, THREADS);
- }
- for(n=THREADS-1; n>=0; n--)
- {
- free(threadstuff[n].allocs); threadstuff[n].allocs=0;
- free(threadstuff[n].toalloc); threadstuff[n].toalloc=0;
- }
- return opspersec;
-}
-
-int main(void)
-{
- double std=0, ned=0;
-
-#if 0
- {
- usCount start, end;
- start=GetUsCount();
- THREADSLEEP(5000);
- end=GetUsCount();
- printf("Wait was %lf\n", (end-start)/1000000000000.0);
- }
-#endif
-#ifdef WIN32
- { /* Force load of user32.dll so we can debug */
- BOOL v;
- SystemParametersInfo(SPI_GETBEEP, 0, &v, 0);
- }
-#endif
-
- if(0)
- {
- printf("\nTesting standard allocator with %d threads ...\n", THREADS);
- std=runtest();
- }
- if(1)
- {
- printf("\nTesting nedmalloc with %d threads ...\n", THREADS);
- whichmalloc=1;
- ned=runtest();
- }
-#ifdef WIN32
-/*
- if(0)
- {
- ULONG data=2;
- win32heap=HeapCreate(0, 0, 0);
- HeapSetInformation(win32heap, HeapCompatibilityInformation, &data, sizeof(data));
- HeapQueryInformation(win32heap, HeapCompatibilityInformation, &data, sizeof(data), NULL);
- if(2!=data)
- {
- printf("The win32 low frag allocator won't work under a debugger!\n");
- }
- else
- {
- printf("Testing win32 low frag allocator with %d threads ...\n\n", THREADS);
- whichmalloc=2;
- runtest();
- }
- HeapDestroy(win32heap);
- }
-*/
-#endif
- if(std && ned)
- { // ned should have more ops/sec
- printf("\n\nnedmalloc allocator is %lf times faster than standard\n", ned/std);
- }
- printf("\nPress a key to trim\n");
- getchar();
- nedmalloc_trim(0);
-#ifdef _MSC_VER
- printf("\nPress a key to end\n");
- getchar();
-#endif
- return 0;
-}


Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk