
So far, the answer seems to involve referring to boost implementation details, which doesn't thrill me.I just wanted to create some memory-pools that could be used to allocate objects referred to through boost:shared_ptr<>.I want to avoid non-pool memory-allocation, and for each shared-object allocation to involve one (and only one) allocation from one pool, i.e. to be as predictable and compact as possible. This hand-written definition for a pool and an allocator seem to do what I want: ---------- template<typename T> class my_pool { private: char *rawStorage; T *storage; T *nextFree; public: my_pool(size_t S) : storage(nullptr), nextFree(nullptr) { // Allocate memory. rawStorage = new char[sizeof(T) * S]; storage = reinterpret_cast<T*>( rawStorage ); // All objects are free, initially. for (size_t i = 0; i < S; ++i) { T **pFreeObject = reinterpret_cast<T**>(&storage[i]); *pFreeObject = nextFree; nextFree = reinterpret_cast<T*>(&storage[i]); } } ~my_pool() { // TODO: Verify that all allocated objects have been freed. delete[] rawStorage; } T *allocate() { T *freeObject = nextFree; if (nextFree != nullptr) { T **pFreeObject = reinterpret_cast<T**>(nextFree); nextFree = *pFreeObject; } return freeObject; } void deallocate(T *obj) { T **pFreeObject = reinterpret_cast<T**>(obj); *pFreeObject = nextFree; nextFree = obj; } }; template<typename T> class my_allocator : public at_boost::detail::sp_ms_deleter<T> { public: typedef at_boost::detail::sp_counted_impl_pda<T *, at_boost::detail::sp_ms_deleter<T>, my_allocator<T> > shared_type; typedef my_pool<shared_type> pool_type; private: pool_type &m_rPool; void operator=(my_allocator const &other); // Disallow assignment. public: explicit my_allocator(pool_type &a_rPool) : m_rPool(a_rPool) { } my_allocator(my_allocator const &other) : m_rPool(other.m_rPool) { } template <typename U> struct rebind { typedef my_allocator/*<U>*/ other; }; shared_type *allocate(int iCount) { if (iCount == 1) // Only expected to allocate single objects. return m_rPool.allocate(); return nullptr; } void deallocate(shared_type *obj, size_t iCount) { m_rPool.deallocate(obj); } }; ---------- It still needs polish, but it's just a proof of concept. Here's some code that uses the pool/allocator: ---------- my_allocator<int>::pool_type myPool (1024); my_allocator<int> myAllocator(myPool); boost::shared_ptr<int> pTest = boost::allocate_shared<int, my_allocator<int> >(myAllocator); int iVal0 = *pTest; *pTest = sizeof(my_allocator<int>::shared_type); int iVal1 = *pTest; ---------- No big deal. Mostly, the test is to make sure that ::operator new() doesn't get called after the construction of the pool, and that seems to be true. I'm surprised that my expected usage of memory-pools isn't more common.Maybe using boost in an environment with constraints on dynamic memory allocation is unusual? Also, at some point, I need to figure out why my definition of my_allocator<T>::rebind can't use <U> in the way that the standard boost allocators do.I get an incomprehensible error-message when I do that: ---------- boost\smart_ptr\detail\sp_counted_impl.hpp(237): error C2664: 'my_allocator<T>::my_allocator(my_pool<at_boost::detail::sp_counted_impl_pda<P,D,A>> &)' : cannot convert parameter 1 from 'my_allocator<T>' to 'my_pool<T> &'---------- Any comments on what I'm trying to do here? -Steven