head	1.1;
access;
symbols;
locks; strict;
comment	@# @;


1.1
date	2005.09.09.01.18.12;	author myevan;	state Exp;
branches;
next	;


desc
@@


1.1
log
@ó 
@
text
@#pragma once

#include "Sync.h"

#include <assert.h>
#include <typeinfo.h>

#include <algorithm>
#include <vector>


#define ETER_POOL

namespace eter {

template<typename T, int PRESERVE_SIZE=0>
class pool
{	
	public:
		pool()
		{
			m_uInitCapacity = 0;
			m_uUsedCapacity = 0;
			m_uUsedPreserve = 0;
			m_uMaxPreserve = 0;
			m_nRestAllocCount = 0;

			m_akPreserve = NULL;

			if (PRESERVE_SIZE>0)
				InitPreserve(PRESERVE_SIZE);
		}
		~pool()
		{
			Destroy();			
		}

		void SetStrictFreeCheck(bool isEnable)
		{
			m_isEnableStrictFreeCheck = isEnable
		}

		void Destroy()
		{	
			assert (0 == m_nRestAllocCount);
#ifndef _DEBUG
			if (m_vec_pkData.size() > PRESERVE_SIZE)
#endif
			{
				FILE* fp = fopen("pool.log", "a+");
				if (fp)
				{
					fprintf(fp, "pool %s used(%d) > preserve(%d)\n", 
						typeid(T).name(), m_uUsedPreserve + m_vec_pkData.size(), PRESERVE_SIZE);
					fclose(fp);
				}
			}

			if (m_akPreserve)
			{
				delete [] m_akPreserve;
				m_akPreserve = NULL;

				m_uUsedPreserve = 0;
			}
			
			std::for_each(m_vec_pkData.begin(), m_vec_pkData.end(), __DeleteData);



			m_vec_pkData.clear();
			m_vec_pkFree.clear();
		}

		void InitCapacity(UINT uCapacity)
		{
			m_uInitCapacity = uCapacity;

			m_vec_pkData.reserve(m_uInitCapacity);
			m_vec_pkFree.reserve(m_uInitCapacity);
		}
		void InitPreserve(UINT uPreserve)
		{
			m_uMaxPreserve = uPreserve;

			m_uUsedPreserve = 0;
			
			if (m_uMaxPreserve > 0)
			{
				if (NULL != m_akPreserve)
					delete [] m_akPreserve;
					
				m_akPreserve = new char[sizeof(T)*m_uMaxPreserve];
			}			
		}

		T* Alloc()
		{
#ifdef _DEBUG
			++m_nRestAllocCount;
#endif
			if (m_vec_pkFree.empty())
			{
				T* pkNewData = NULL;
				
				if (m_uUsedPreserve < m_uMaxPreserve)
				{
					pkNewData = ((T*)m_akPreserve) + (m_uUsedPreserve++);					
				}
				else
				{
					pkNewData = __NewData();				
					m_vec_pkData.push_back(pkNewData);
				}
				++m_uUsedCapacity;
				return pkNewData;
			}

			T* pkFreeData = m_vec_pkFree.back();
			m_vec_pkFree.pop_back();
			return pkFreeData;
		}
		void Free(T* pkData)
		{			
#ifdef _DEBUG
			--m_nRestAllocCount;

			if (m_isEnableStrictFreeCheck)
			{
				assert(__IsValidData(pkData));
				assert(!__IsFreeData(pkData));
			}
#endif
			m_vec_pkFree.push_back(pkData);
		}

		void FreeAll()
		{
			m_vec_pkFree = m_vec_pkData;
			m_uUsedPreserve = 0;
			m_nRestAllocCount = 0;
		}
		
		DWORD GetAllocCount()
		{
			return m_vec_pkData.size() + m_uUsedPreserve;
		}

	protected:
		bool __IsValidData(T* pkData)
		{
			if (pkData >= ((T*)m_akPreserve) && pkData < ((T*)m_akPreserve) + m_uMaxPreserve)
				return true;

			if (m_vec_pkData.end() == std::find(m_vec_pkData.begin(), m_vec_pkData.end(), pkData))
				return false;
			return true;
		}
		bool __IsFreeData(T* pkData)
		{
			if (m_vec_pkFree.end() == std::find(m_vec_pkFree.begin(), m_vec_pkFree.end(), pkData))
				return false;

			return true;
		}

		static T* __NewData()
		{
			return (T*)::operator new(sizeof(T));
		}

		static void __DeleteData(T* pkData)
		{
			::operator delete(pkData);			
		}

	protected:
		std::vector<T*> m_vec_pkData;
		std::vector<T*> m_vec_pkFree;

		char* m_akPreserve;

		unsigned int m_uUsedPreserve;
		unsigned int m_uMaxPreserve;
		unsigned int m_uInitCapacity;
		unsigned int m_uUsedCapacity;
		int m_nRestAllocCount;

		bool m_isEnableStrictFreeCheck;
};

template <class T, int PRESERVE_SIZE=0>
class pooled_object
{
	public:
		typedef pool<T, PRESERVE_SIZE> SELF_TYPE;

    public:
		pooled_object()
		{
		}
		virtual ~pooled_object()
		{
		}

        void * operator new(unsigned int mem_size)
        {
            return ms_pool.Alloc();
        }
		
        void operator delete(void* pT)
        {
            ms_pool.Free((T*)pT);
        }
			
		static SELF_TYPE& GetSharedPool()
		{
			return ms_pool;
		}
        
    protected:
        static SELF_TYPE ms_pool;
};

template <class T, int PRESERVE_SIZE> 
pool<T, PRESERVE_SIZE> pooled_object<T, PRESERVE_SIZE>::ms_pool;


template <class T, int PRESERVE_SIZE=0>
class pooled_object_thread_safe
{
public:
	typedef pool<T, PRESERVE_SIZE> SELF_TYPE;
	
public:
	pooled_object_thread_safe()
	{
	}
	virtual ~pooled_object_thread_safe()
	{
	}
	
    void * operator new(unsigned int mem_size)
    {			
		SLock kLock(ms_kSync.Lock());
        return ms_pool.Alloc();
    }
	
    void operator delete(void* pT)
    {
		SLock kLock(ms_kSync.Lock());
        ms_pool.Free((T*)pT);
    }
	
	static SELF_TYPE& GetSharedPool()
	{
		return ms_pool;
	}
	
protected:
    static SELF_TYPE ms_pool;
	static SSync ms_kSync;
};

template <class T, int PRESERVE_SIZE> 
pool<T, PRESERVE_SIZE> pooled_object_thread_safe<T, PRESERVE_SIZE>::ms_pool;

template <class T, int PRESERVE_SIZE> 
SSync pooled_object_thread_safe<T, PRESERVE_SIZE>::ms_kSync;

} // eter@
