Click here to Skip to main content
15,888,320 members
Articles / Programming Languages / C++

Object Pooling for Generic C++ classes

Rate me:
Please Sign up or sign in to vote.
3.29/5 (19 votes)
4 May 2003CPOL2 min read 78.5K   2.3K   31  
Implements a basic object pooling scheme for generic C++ objects.
#ifndef __OBJPOOL_H__
#define __OBJPOOL_H__

#pragma once // WATCOM special to include a header only once

class clsCrit
{
private:
CRITICAL_SECTION _Crit;

clsCrit(const clsCrit&) // NO NO NO NO! No copy constructor!!!
{
}
public:
	clsCrit(void) 
	{ 
		InitializeCriticalSection(&_Crit); 
	}
	~clsCrit(void) 
	{ 
		DeleteCriticalSection(&_Crit); 
	}

	void Enter(void) const
	{ 
		EnterCriticalSection(const_cast<CRITICAL_SECTION*>(&_Crit));
	}
	void Leave(void) const
	{
		LeaveCriticalSection(const_cast<CRITICAL_SECTION*>(&_Crit));
	}
};

class clsCritObj
{
private:
	const clsCrit* _pCrit;
public:
	clsCritObj(const clsCrit& Sync) 
	{ 
		(_pCrit = &Sync)->Enter(); 
	}
	~clsCritObj(void)   
	{ 
		_pCrit->Leave(); 
	}
};

typedef void* _CHK_PVOID;

template<int S>
class clsPointerArray
{
private:
	_CHK_PVOID* _Array;
	int _nEntriesAllocated;
	int _nEntriesUsed;

public:
	clsPointerArray(void)
	{
		_Array = NULL;
		_nEntriesUsed = 0;
		_nEntriesAllocated = 0;
	}
	virtual ~clsPointerArray(void)
	{
		if (_nEntriesUsed)
			_chk_utildebug(TEXT("WRN: objects left in pool!"));
	}

	void* Get(void)
	{
		if (_nEntriesUsed <= 0)
			return(NULL);
		return(_Array[--_nEntriesUsed]);
	}
	void Add(void* p)
	{
		if (_nEntriesUsed + 1 > _nEntriesAllocated)
		{
			_CHK_PVOID* pNew = ::new _CHK_PVOID[_nEntriesAllocated + S];
			memcpy(pNew,_Array,_nEntriesUsed * sizeof(_CHK_PVOID));
			_nEntriesAllocated += S;
			delete[] _Array;
			_Array = pNew;
		}
		_Array[_nEntriesUsed++] = p;
	}
};

template <class T, int S = 16> // S = size increment in pool allocation
class clsObjectPool
{
private:
	#if !_OBJPOOL_NO_MULTITHREADING
	static clsCrit& CS(void)
	{
		static clsCrit __Crit;
		return(__Crit);
	}
	#endif

	static clsPointerArray<S>& List(void)
	{
		static clsPointerArray<S> __FreeItems;
		return(__FreeItems);
	}

public:
	clsObjectPool() 
	{
	}

	virtual ~clsObjectPool() 
	{
	}

	void* operator new(size_t stAllocateBlock)
	{
		#if !_OBJPOOL_NO_MULTITHREADING
		clsCritObj CO(CS());
		#endif

		clsPointerArray<S>& VList(T::List());
		void* pNewObject(VList.Get());

		if (pNewObject == NULL)
		pNewObject = ::new T;
		return(pNewObject);
	}

	void operator delete(void *p)
	{
		#if !_OBJPOOL_NO_MULTITHREADING
		clsCritObj CO(CS());
		#endif

		clsPointerArray<S>& VList(T::List());

		VList.Add(p);
	}
	
	void Clear(void)
	{
		#if !_OBJPOOL_NO_MULTITHREADING
		clsCritObj CO(CS());
		#endif

		clsPointerArray<S>& VList(T::List());

		while (true)
		{
			void* pObject(VList.Get());
			if (pObject == NULL)
			break;
			::delete reinterpret_cast<T*>(pObject);
		}
	}
};

#endif

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



Comments and Discussions