$include_dir="/home/hyper-archives/boost-commit/include"; include("$include_dir/msg-header.inc") ?>
From: xushiweizh_at_[hidden]
Date: 2008-04-30 04:43:08
Author: xushiwei
Date: 2008-04-30 04:43:07 EDT (Wed, 30 Apr 2008)
New Revision: 44920
URL: http://svn.boost.org/trac/boost/changeset/44920
Log:
ticket #1885: release gc_alloc (pre-alpha)
Text files modified: 
   sandbox/memory/boost/memory/basic.hpp    |     4 -                                       
   sandbox/memory/boost/memory/gc_alloc.hpp |   153 +++++++++++++++++++++++++++------------ 
   sandbox/memory/boost/memory/policy.hpp   |     1                                         
   3 files changed, 107 insertions(+), 51 deletions(-)
Modified: sandbox/memory/boost/memory/basic.hpp
==============================================================================
--- sandbox/memory/boost/memory/basic.hpp	(original)
+++ sandbox/memory/boost/memory/basic.hpp	2008-04-30 04:43:07 EDT (Wed, 30 Apr 2008)
@@ -199,10 +199,6 @@
 };																			\
 _NS_BOOST_END
 
-#define BOOST_INT_NO_DESTRUCTOR(Type)										\
-	BOOST_NO_DESTRUCTOR(unsigned Type);										\
-	BOOST_NO_DESTRUCTOR(signed Type)
-
 // -------------------------------------------------------------------------
 // BOOST_NO_CONSTRUCTOR
 
Modified: sandbox/memory/boost/memory/gc_alloc.hpp
==============================================================================
--- sandbox/memory/boost/memory/gc_alloc.hpp	(original)
+++ sandbox/memory/boost/memory/gc_alloc.hpp	2008-04-30 04:43:07 EDT (Wed, 30 Apr 2008)
@@ -123,7 +123,11 @@
                         _MemHeader* BOOST_MEMORY_CALL first() const {
                                 return (_MemHeader*)m_start;
                         }
+			_MemHeader* BOOST_MEMORY_CALL current() const {
+				return (_MemHeader*)m_start;
+			}
                         _MemHeader* BOOST_MEMORY_CALL next() {
+				BOOST_MEMORY_ASSERT(!done());
                                 m_start += sizeof(_MemHeader) + ((_MemHeader*)m_start)->cbSize;
                                 return (_MemHeader*)m_start;
                         }
@@ -137,7 +141,7 @@
         struct _Pred : std::binary_function<_FreeMemHeader*, _FreeMemHeader*, bool>
         {
                 bool operator()(_FreeMemHeader* a, _FreeMemHeader* b) const {
-			return a->cbSize > b->cbSize;
+			return a->cbSize < b->cbSize;
                 }
         };
         typedef std::deque<_FreeMemHeader*> _Cont;
@@ -150,9 +154,21 @@
         _MemBlock* m_blockList;
         _PriorityQ m_freeList;
         _HugeGCAlloc m_hugeAlloc;
+	size_t m_freeSize, m_GCLimitSize;
         static _FreeMemHeader _null;
 
 private:
+	enum { HeaderSize = sizeof(void*) };
+	enum { BlockSize = MemBlockSize - HeaderSize };
+	enum { _AllocSizeBigDef = MAX(_Policy::AllocSizeBig, BlockSize/4) };
+	enum { _AllocSizeHugeDef = MAX(_Policy::AllocSizeHuge, 64*1024) };
+	enum { _GCLimitSizeDef = MAX(_Policy::GCLimitSizeDef, 64*1024) };
+	enum { AllocSizeBig = MIN(_AllocSizeBigDef, BlockSize/2) };
+	enum { AllocSizeHuge = MIN(_AllocSizeHugeDef, (1 << 29)) };
+	enum { GCLimitSizeDef = MIN(_GCLimitSizeDef, (1 << 29)) };
+	enum { RecycleSizeMin = MAX(_Policy::RecycleSizeMin, 128) };
+
+private:
         const gen_alloc& operator=(const gen_alloc&);
 
         static bool BOOST_MEMORY_CALL _IsValid(void* obj, size_t cb, destructor_t fn)
@@ -198,35 +214,84 @@
                 }
         }
 
-	void BOOST_MEMORY_CALL _ReduceDestroyChain() const
+public:
+	void BOOST_MEMORY_CALL force_gc()
         {
-		_MemHeaderEx** pp = &m_destroyChain;
-		while (*pp)
-		{
-			_MemHeaderEx* curr = (*pp)->pPrev;
-			if (curr->blkType == nodeFree) {
-				*pp = curr->pPrev;
-			}
-			else {
-				pp = &curr->pPrev;
-			}
-		}
-	}
+		// 0. Prepare
 
-	void BOOST_MEMORY_CALL _Travel() const
-	{
+		// 0.1. Commit current block:
+		_CommitCurrentBlock();
+		m_begin = m_end = _null.getData();
+
+		// 0.2. Clear destroy chain
+		m_destroyChain = NULL;
+
+		// 0.3. Clear free list
+		m_freeList.clear();
+		m_freeSize = 0;
+
+		// 1. Collect free nodes
                 _MemBlock* pHeader = m_blockList;
                 while (pHeader)
                 {
-			_MemBlock::Enumerator coll(pHeader->pPrev);
+			_MemBlock::Enumerator coll(m_alloc, pHeader);
                         pHeader = pHeader->pPrev;
-			for (_MemHeader* it = coll.first(); !coll.done(); it = coll.next())
-				it;
+			for (;;)
+			{
+				if (coll.done())
+					break;
+				_MemHeader* it = coll.current();
+				if (it->blkType == nodeFree)
+				{
+					// merge nodes marked with nodeFree
+					UINT cbFree = it->cbSize;
+					for (;;) {
+						_MemHeader* it2 = coll.next();
+						if (coll.done() || it2->blkType != nodeFree)
+							break;
+						cbFree += it2->cbSize;
+					}
+					it->cbSize = cbFree;
+					if (cbFree >= RecycleSizeMin)
+						m_freeList.push((_FreeMemHeader*)it);
+					if (coll.done())
+						break;
+					it = coll.current();
+				}
+				if (it->blkType == nodeAllocedWithDestructor)
+				{
+					_MemHeaderEx* itEx = (_MemHeaderEx*)it;
+					itEx->pPrev = m_destroyChain;
+					m_destroyChain = itEx;
+				}
+				// skip nodes marked with nodeAlloced
+				coll.next();
+			}
                 }
         }
+	
+	void BOOST_MEMORY_CALL try_gc()
+	{
+		if (m_freeSize >= m_GCLimitSize)
+			force_gc();
+	}
 
-	void BOOST_MEMORY_CALL _TryGC()
+	size_t BOOST_MEMORY_CALL get_free_size() const
         {
+		return m_freeSize;
+	}
+
+	void BOOST_MEMORY_CALL set_gclim(size_t gcLimit)
+	{
+		m_GCLimitSize = gcLimit;
+	}
+
+private:
+	void BOOST_MEMORY_CALL _CommitCurrentBlock()
+	{
+		_FreeMemHeader* old = (_FreeMemHeader*)m_begin - 1;
+		BOOST_MEMORY_ASSERT(old->getBlockType() == nodeFree);
+		old->cbSize = (m_end - m_begin);
         }
 
         _MemHeader* BOOST_MEMORY_CALL _NewBlock(size_t cbBlock)
@@ -241,42 +306,26 @@
                 return pNew;
         }
 
-	void BOOST_MEMORY_CALL _CommitCurrentBlock()
-	{
-		_FreeMemHeader* old = (_FreeMemHeader*)m_begin - 1;
-		BOOST_MEMORY_ASSERT(old->getBlockType() == nodeFree);
-		old->cbSize = (m_end - m_begin);
-	}
-
         void BOOST_MEMORY_CALL _Init()
         {
+		m_blockList = NULL;
+		m_destroyChain = NULL;
+		m_freeSize = 0;
+		m_GCLimitSize = GCLimitSizeDef;
+
                 _MemHeader* pNew = _NewBlock(MemBlockSize);
                 m_begin = (char*)(pNew + 1);
                 m_end = m_begin + pNew->cbSize;
         }
 
-private:
-	enum { HeaderSize = sizeof(void*) };
-	enum { BlockSize = MemBlockSize - HeaderSize };
-	enum { _AllocSizeBigDef = MAX(_Policy::AllocSizeBig, BlockSize/4) };
-	enum { _AllocSizeHugeDef = MAX(_Policy::AllocSizeHuge, 64*1024) };
-	enum { AllocSizeBig = MIN(_AllocSizeBigDef, BlockSize/2) };
-	enum { AllocSizeHuge = MIN(_AllocSizeHugeDef, (1 << 29)) };
-	enum { RecycleSizeMin = MAX(_Policy::RecycleSizeMin, 128) };
-
 public:
-	gen_alloc() : m_blockList(NULL), m_destroyChain(NULL)
-	{
+	gen_alloc() {
                 _Init();
         }
-	explicit gen_alloc(_Alloc alloc)
-		: m_alloc(alloc), m_blockList(NULL), m_destroyChain(NULL)
-	{
+	explicit gen_alloc(_Alloc alloc) : m_alloc(alloc) {
                 _Init();
         }
-	explicit gen_alloc(gen_alloc& owner)
-		: m_alloc(owner.m_alloc), m_blockList(NULL), m_destroyChain(NULL)
-	{
+	explicit gen_alloc(gen_alloc& owner) : m_alloc(owner.m_alloc) {
                 _Init();
         }
 
@@ -291,6 +340,8 @@
                 std::swap(m_end, o.m_end);
                 std::swap(m_blockList, o.m_blockList);
                 std::swap(m_destroyChain, o.m_destroyChain);
+		std::swap(m_freeSize, o.m_freeSize);
+		std::swap(m_GCLimitSize, o.m_GCLimitSize);
                 m_alloc.swap(o.m_alloc);
                 m_freeList.swap(o.m_freeList);
                 m_hugeAlloc.swap(o.m_hugeAlloc);
@@ -315,6 +366,7 @@
                 m_begin = m_end = _null.getData();
                 m_blockList = NULL;
                 m_freeList.clear();
+		m_freeSize = 0;
         }
 
         void* BOOST_MEMORY_CALL allocate(size_t cbData)
@@ -338,7 +390,7 @@
                         }
                         else
                         {
-				_TryGC();
+				try_gc();
                                 _FreeMemHeader* p;
                                 if (m_freeList.empty() || (p = m_freeList.top())->cbSize < cb) {
                                         pNew = _NewBlock(MemBlockSize);
@@ -392,6 +444,7 @@
                         BOOST_MEMORY_ASSERT(p->blkType == nodeAlloced);
 
                         p->blkType = nodeFree;
+			m_freeSize += cbData + sizeof(_MemHeader);
                 }
         }
 
@@ -402,6 +455,7 @@
                 obj->~Type();
                 _MemHeaderEx* p = (_MemHeaderEx*)obj - 1;
                 p->blkType = nodeFree;
+		m_freeSize += sizeof(Type) + sizeof(_MemHeaderEx);
         }
 
         template <class Type>
@@ -409,15 +463,19 @@
         {
                 _MemHeader* p = (_MemHeader*)obj - 1;
                 p->blkType = nodeFree;
+		m_freeSize += sizeof(Type) + sizeof(_MemHeader);
         }
 
         template <class Type>
         void BOOST_MEMORY_CALL _DestroyArray(Type* array, size_t count, destructor_t)
         {
-		destructor_traits<Type>::destructArrayN(array, count);
-		void* pData = destructor_traits<Type>::getArrayBuffer(array);
+		typedef destructor_traits<Type> _Traits;
+
+		_Traits::destructArrayN(array, count);
+		void* pData = _Traits::getArrayBuffer(array);
                 _MemHeaderEx* p = (_MemHeaderEx*)pData - 1;
                 p->blkType = nodeFree;
+		m_freeSize += _Traits::getArrayAllocSize(count) + sizeof(_MemHeaderEx);
         }
 
         template <class Type>
@@ -425,6 +483,7 @@
         {
                 _MemHeader* p = (_MemHeader*)array - 1;
                 p->blkType = nodeFree;
+		m_freeSize += sizeof(Type) * count + sizeof(_MemHeaderEx);
         }
 
 public:
Modified: sandbox/memory/boost/memory/policy.hpp
==============================================================================
--- sandbox/memory/boost/memory/policy.hpp	(original)
+++ sandbox/memory/boost/memory/policy.hpp	2008-04-30 04:43:07 EDT (Wed, 30 Apr 2008)
@@ -131,6 +131,7 @@
         enum { RecycleSizeMin = 256 };
         enum { AllocSizeBig = Default };
         enum { AllocSizeHuge = 1024*1024 };
+	enum { GCLimitSizeDef = 1024*1024 };
 
         typedef simple_gc_alloc<system_alloc> huge_gc_allocator;
 };