This section of the archives stores flipcode's complete Developer Toolbox collection, featuring a variety of mini-articles and source code contributions from our readers.

| Object Pool Lite Submitted by

Here is an implementation of object pooling for c++ written with speed (obviously) and minimal impact on existing code as the prime concerns. Thanks to some friendly preprocessor macros, you can modify a class to use this pooling with the addition of just two lines of code. For example, the class:

    class pumpkin {
    	float radius, weight;
    };

becomes:

    class pumpkin {
    	POOLING_MEMBERS(pumpkin)
    	float radius, weight;
    };

and somewhere in the .cpp file you need the line POOLING_FUNCTIONS(pumpkin) - okay so there's three lines to add because you have to #include <object_pool.h>, I was just seeing if you noticed... The pool keeps an array of pointers to the type of object it is pooling, and an index in this array. When an object pointer is requested, the index is incremented and the pointer at that index is returned. When an object pointer is deleted, the index is simply decremented. If all object pointers in the pool are in use when another request occurs, the size of the pool is doubled (only one call to 'new') before continuing as normal. There is no use of a linked list because um... they generally call 'new' which is what we're trying to avoid. The stack type storage means that a memory block can be allocated in amortized constant time - here are some speed improvements measured (Redhat 6.1 P3-600MHz):
(Object size | Percent of standard allocation time taken)
1 byte 14%
36 bytes 13%
100 bytes 6%
1k bytes 1%Even allocation of one byte is quicker than standard allocation! Pros:

> - Portable (tested with MSVC/Linux gcc)
> - O(1) allocation.
> - No preallocation, pool grows adaptively.
> - Small - here in its entirety on this page (below)

Cons:

> - Fixed size blocks means that separate pools are created even for objects which may be of equal size and could have shared one pool.
> - No means of reducing the pool size when not in use.

    #ifndef OBJECT_POOL_TEMPLATE
    #define OBJECT_POOL_TEMPLATE

    #include <vector

    #define POOLING_MEMBERS(classname) \
    public:\
    	static void* operator new(size_t size);\
    	static void operator delete(void* ptr, size_t size);\
    	static object_pool<classname m_pool;

    #define POOLING_FUNCTIONS(classname) \
    void* classname::operator new(size_t p_size) {\
        return m_pool.newObject(p_size);\
    }\
    void classname::operator delete(void* p_ptr, size_t p_size) {\
        m_pool.deleteObject(p_ptr, p_size);\
    }\
    object_pool<classname classname::m_pool;

    template <class T class object_pool
    {

    private:

        unsigned char ** m_freeBlocks;
        size_t m_size;
    	long m_available;
    	std::vector<void* m_validHeapPtrs;
    	long m_bufferSize;

    public:

        object_pool()
    	{
    		m_size = sizeof(T);
    		m_available = 0;
    		m_bufferSize = 1;
    		m_freeBlocks = new unsigned char*[m_bufferSize];
    		unsigned char * t_ptr = new unsigned char[m_size*m_bufferSize];
    		m_validHeapPtrs.push_back(t_ptr);
    		m_freeBlocks[m_available++] = t_ptr;
    	};

        ~object_pool()
    	{
    		for (int i = 0; i < m_validHeapPtrs.size(); i++) {
    			::operator delete(m_validHeapPtrs[i]);
    		}
    		m_validHeapPtrs.clear();
    		::operator delete(m_freeBlocks);
    	}

        void* newObject(size_t p_size)
    	{
    		if(p_size != m_size) {
    			return ::operator new(p_size);
    		} else if (m_available  0) {
    			return m_freeBlocks[--m_available];
    		} else {
    			::operator delete(m_freeBlocks);
    			m_freeBlocks = new unsigned char*[m_bufferSize*2];
    			unsigned char *t_ptr = new unsigned
    char[m_size*m_bufferSize];
    			m_validHeapPtrs.push_back(t_ptr);
    			unsigned char *t_tp = t_ptr + m_size;
    			for (int i = 1; i < m_bufferSize; i++) {
    				m_freeBlocks[m_available++] = t_tp;
    				t_tp += m_size;
    			}
    			m_bufferSize *= 2;
    			return t_ptr;
    		}
    	}

        void deleteObject(void* p_ptr, size_t p_size)
    	{
    		if(p_size != m_size){
    			::operator delete(p_ptr);
    		} else {
    			m_freeBlocks[m_available++] = (unsigned char*)p_ptr;
    		}
    	}

    };
    #endif

The zip file viewer built into the Developer Toolbox made use of the zlib library, as well as the zlibdll source additions.

Copyright 1999-2008 (C) FLIPCODE.COM and/or the original content author(s). All rights reserved.
Please read our Terms, Conditions, and Privacy information.