type_pool  1.2
 All Classes Files Functions Typedefs

Introduction

type_pool is a memory pool for a given type T. To be frank, I don't know that it may be of real use because of that particularity. Why do I do it? I'm not sure I remember. Well, I'll file it under "it's good C++11 practice". And 'tis a fine day the day you can write cross-platform multi-threaded code without Boost...

Now, 'tis also unfortunate that VC11 does not support variadic templates because if it did, I could "perfect forward" the set of a T's constructor arguments a la std::make_shared<T>. For the time being, a T must be constructed on the stack by you and it will be moved in the allocated memory. This points out a defining restriction: type_pool should only be used with type that have a move constructor. This is the case because the memory pool works in fixed-size memory chunks.

But enough of putting this project down. Here's a memory pool that will serve you raw pointers, shared_ptr<T>s and unique_ptr<T>s from a memory pool.

Technical considerations

This implementation:

Optimizations

Only one optimization is available at this time.

Preallocation

Memory pre-allocation can be requested when instantiating the pool. It will be performed on a separate thread. Note that the first allocation requested will wait until preallocation is over.

Improvements

I got me a Todo list.

Sample code

#include "type_pool.h"

#include <cstdint>
#include <string>

using namespace std;

class A
{
    int k;

public:
    A(int k) : k(k)
    {
        int i = 22;
    }

    A(A&& a)
    {
        k = a.k;
        a.k = 0;
    }

    virtual ~A()
    {
        k = -1;
    }
};

class B : public A
{
    int l;

public:
    B(int l) : A(l * 2), l(l)
    {}
};

class C
{
    string s;

public:
    C(string&& s) : s(move(s))
    {
    }
};

int main()
{
    {
        // Instantiate a pool for ints.
        type_pool<int> pi;

        // Get two integers. These will trigger allocation of new memory.
        // Their memory will return to the pool when they go out of scope.
        {
            shared_ptr<int> i = pi.get_shared(1);

            type_pool<int>::unique_ptr j = pi.get_unique(2);
        }

        // Get two more integers.
        // This time, we reuse memory from the pool's free store.
        // Their memory will also return to the pool when they go out of scope.
        {
            shared_ptr<int> i = pi.get_shared(11);

            type_pool<int>::unique_ptr j = pi.get_unique(22);
        }

        // All memory from the pool is reclaimed here.
    }


    {
        // Instantiate a pool for As.
        // Preallocate memory for three As.
        type_pool<A> pa(3);

        // Get two As.
        // Memory for these has already been preallocated.
        // Their memory will return to the pool when they go out of scope.
        {
            shared_ptr<A> i = pa.get_shared(A(3));

            type_pool<A>::unique_ptr j = pa.get_unique(A(4));
        }

        // All memory from the pool is reclaimed here.
    }

    
    {
        // Instantiates a pool for floats.
        // Set its maximum capacity to two floats.
        type_pool<float> pf(0, 2);

        // Get three floats. These will trigger allocation of new memory.
        // The memory of two of the three floats will return to the pool when they go out of scope.
        {
            shared_ptr<float> i = pf.get_shared(1.f), j = pf.get_shared(2.f), k = pf.get_shared(3.f);
        }

        // Get three more floats.
        // We will reuse memory from the pool's free store for the first two floats.
        // Again, the memory of two of the three floats will return to the pool when they go out of scope.
        {
            shared_ptr<float> i = pf.get_shared(1.f), j = pf.get_shared(2.f), k = pf.get_shared(3.f);
        }

        // All memory from the pool is reclaimed here.
    }


#if (defined(__GNUG__) && (GCC_VERSION >= 40400))
    {
        // Same as before but now we exercise the function with variadic template parameters.

        type_pool<C> pc;

        {
            shared_ptr<C> i = pc.get_shared<C>("string");

            type_pool<C>::unique_ptr j = pc.get_unique<C>("string");
        }
    }
#endif

    // Misuses.

    // shared_ptr<A> b = pa.get_shared(B(6));   // Correctly fails to compile because a B is not exactly an A.

    return 0;
}

License

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.