homogeneous pools accessed trough pointers-> still good?

Started by
2 comments, last by l0k0 10 years, 4 months ago

So if you have a contiguous and homogeneous pool of objects, aiming cache coherence / un-fragmented memory, should you access it directly to keep those memory friendly features?

I created a pool class, but the pool (fixed array) is private, and I want my systems to iterate over the allocated elements (elements on the pool that are in use).

I dont want to make the pool public for obvious reasons (or perhaps I should?), and I cant make it friend of my systems, cause its a templated pool, Id need to put friends declaration for every system..

So after some thinking I come with something like PoolAccess class, which have pointers to the pool data, so it can access pool elements with a function T* GetAllocated(int index). So in the pool class I have a GetAccess that returns PoolAccess that the systems can get.


//basic structure

template<typename T, uint SIZE>
class Pool{

public:

   class PoolAccess{

    PoolAccess(T pool[], Roster * roster );

    T* GetAllocated(uint index);

    private:
    m_pPoolRef;
    m_pRosterRef;

   };

   PoolAccess GetAccess(){

       return PoolAccess(&m_pool, &m_roster);
   }

   T*Alloc();
   void Free(T*);

private:

   Roster m_roster; // the dude that controls the free list(raped from insomniac gdc canada presentation)
   T m_pool[SIZE];
   
};

But than I realized, doesnt that send the cache friendly goal to space?

GetAllocated basically will go trough the m_pRosterRef pointer, go to the given index on the "list" of allocated (also a contiguous array), get the index on the pool, go trough pPoolRef pointer to return the pool element address at the index..

My drawablesQueue have similar access, I have a vector of drawables and a sorted vector of indexes to the drawables, but I remember Hodgman and Spiro saying it was still better accessing that way instead of sorting the drawables itself, so I guess its the same..?almost? Not really?

link to the insomniac presentation in the case you curious

Advertisement

You could provide begin, end, empty, size, operator[], ... methods to get iterators and other information. That lets you avoid having to friend nearly the whole world.

You could avoid pointers and only give an index and/or iterator.

If you like you could also make it use a std::vector internally so it gets resizable and only fill in some parts to make it a pool and provide restricted access.

Yeah, I would provide iterators instead of the GetAllocated() function. The iterators can be made to efficiently keep track of which objects are valid, because you don't have to search backwards. So it basically has a pointer/forward iterator to container indicating which objects are free, and another to the object pointer to, for access.

On a different note, it seems strange to make this a template like that, because it means you have a separate Pool for each type. If you have a lot of types that this is use with, then that's inefficient. If you have a few, it would probably be more clear if you used inheritance to share the common code.
Keep it simple - is there a reason your pool can't set/unset a flag for that index as part of your alloc/dealloc functions? So when iterating through we check this flag and return null if it is set? One separate bit array will be much more memory performant than a list of pointers.
<shameless blog plug>
A Floating Point
</shameless blog plug>

This topic is closed to new replies.

Advertisement