PGE API 0.4
PR00F's Game Engine full documentation
Loading...
Searching...
No Matches
PgeObjectPool< T > Class Template Reference

PR00F's Game Engine object pool for permanently allocating fixed number of game objects. More...

Detailed Description

template<typename T>
class PgeObjectPool< T >

PR00F's Game Engine object pool for permanently allocating fixed number of game objects.

The aim of this class is to have a fixed number of objects being kept in contiguous memory area, and to be able to distinguish between them as they are free for use or busy (being used).

This way we just flag the preallocated objects, instead of actually creating or deleting them in memory which would be otherwise performance-expensive operation, especially when we are talking about resource-heavy objects such as PureObject3D or even higher-level game instances.

Thus, I expect this pool to be used for storing objects created and deleted with high frequency, such as bullets fired from weapons, particles, etc.

Since these virtual "create" and "delete" operations are expected to happen multiple times within 1 frame, I want them to have O(1) complexity.

Also, since they are in contiguous memory area, and usually higher-level logic iterates over them from begin to end, it is more cache-friendly than iterating over occasionally allocated objects that are placed here and there in memory.

The only downsides of having such preallocated object pool is that:

  • we need to have a good guess for the number of required objects to be allocated at the beginning;
  • these preallocated objects are always using memory capacity even when not all is needed.

However, the advantages regarding performance are outweighing these small disadvantages.

Basically this class is based on this "Object Pool Pattern": https://gameprogrammingpatterns.com/object-pool.html .

Also, for iterators, I'm using Vincenzo Barbato's blIteratorAPI: https://github.com/navyenzo/blIteratorAPI . Note that you might need to define the _SILENCE_CXX17_ITERATOR_BASE_CLASS_DEPRECATION_WARNING macro for the MSVC preprocessor, it comes from the way of how blIteratorAPI is implemented. It is safe to silence this warning.

Reminder: this class is NOT a memory pool neither a memory manager. This is an object pool with fixed number of objects, and after construction, no more memory allocation happens! For memory pool management, I would rather use an already existing solution from these:

Ideas on improving:

  • not all iterators can compile currently, as you can see in the unit tests, only begin() and end() are working, but const and reverse iterators don't compile due to warnings and else, need time to fix that in blIteratorAPI.
  • would be nice to implement iterating over only used elems, so that loops would not need to check elem.used(), and this should utilize the elem's next ptr, because currently only the unused elems' next ptr has meaningful value, but the used elem's next ptr is not used for anything, this should be changed to point to next used elem, and then we could have 2 separate lists, 1 with unused elems and 1 with used elems.
  • would be useful to have a bool autoReuseOldestElems flag: it would make difference when create() detects no free object is available. If flag is false, simply return without doing anything (current behavior). If true, it would reuse the oldest used elem, updated with the given params. Use case: for example, particles, like rocket smoke: if pool capacity is reached, it would make sense to reuse the oldest emitted smoke objects, instead of not doing anything.
  • modify blIteratorAPI so that _SILENCE_CXX17_ITERATOR_BASE_CLASS_DEPRECATION_WARNING definition would not be needed.

Definition at line 209 of file PgeObjectPool.h.

#include <PgeObjectPool.h>

+ Inheritance diagram for PgeObjectPool< T >:

Public Member Functions

CConsole & getConsole () const
 
 PgeObjectPool ()
 This constructor should be used when parameters for initializing the pool is NOT available.
 
template<typename... Args>
 PgeObjectPool (const std::string &poolName, const size_t &capacity, Args &&... pooledObjArgs)
 Not only the memory pool is allocated for all pooled objects, but their non-default constructor is also called with the provided pooled object parameters, or their default constructor if that is available.
 
 ~PgeObjectPool ()
 
 PgeObjectPool (const PgeObjectPool &)=delete
 
PgeObjectPooloperator= (const PgeObjectPool &)=delete
 
 PgeObjectPool (PgeObjectPool &&)=delete
 
PgeObjectPool && operator= (PgeObjectPool &&)=delete
 
void deallocate ()
 Frees up the allocated contiguous memory pool, capacity becomes zero, name becomes "unnamed pool".
 
const size_t & count () const
 
const size_t & size () const
 Conventionally std containers have a size() member function returning the number of elements, NOT the capacity.
 
const size_t & capacity () const
 
size_t capacityBytes () const
 
bool empty () const
 
const std::string & name () const
 
template<typename... Args>
T * create (Args &&... pooledObjArgs)
 Finds a free (usable) object in the pool, sets it flag as used and returns it.
 
void remove (PgePooledObject &obj)
 Resets the free (usable) flag of this object, "returns it" into the pool so it can be reused again.
 
blIteratorAPI::blRawArrayWrapper< T >::iterator erase (typename blIteratorAPI::blRawArrayWrapper< T >::iterator itPos)
 Resets the free (usable) flag of the pooled object pointed by the given iterator, "returns" the object into the pool so it can be reused again.
 
template<typename... Args>
void reserve (const std::string &poolName, const size_t &capacity, Args &&... pooledObjArgs)
 Not only the memory pool is allocated for all pooled objects, but their non-default constructor is also called with the provided pooled object parameters, or their default constructor if that is available.
 
void clear ()
 Resets the free (usable) flag of all objects in the pool, "returns them" into the pool so they can be reused again.
 
T * elems ()
 
const T * elems () const
 
blIteratorAPI::blRawArrayWrapper< T > rawArrayWrapper ()
 
blIteratorAPI::blRawArrayWrapper< T >::iterator begin ()
 Gives iterator for beginning iterating over the contiguous memory area of pooled objects, the same area that elems() returns.
 
blIteratorAPI::blRawArrayWrapper< T >::iterator end ()
 Gives iterator for ending iterating over the contiguous memory area of pooled objects, the same area that elems() returns.
 
blIteratorAPI::blRawArrayWrapper< T >::const_iterator cbegin () const
 Gives const iterator for beginning iterating over the contiguous memory area of pooled objects, the same area that elems() returns.
 
blIteratorAPI::blRawArrayWrapper< T >::const_iterator cend () const
 Gives const iterator for ending iterating over the contiguous memory area of pooled objects, the same area that elems() returns.
 
blIteratorAPI::blRawArrayWrapper< T >::reverse_iterator rbegin ()
 Gives iterator for beginning reverse iterating over the contiguous memory area of pooled objects, the same area that elems() returns.
 
blIteratorAPI::blRawArrayWrapper< T >::reverse_iterator rend ()
 Gives iterator for ending reverse iterating over the contiguous memory area of pooled objects, the same area that elems() returns.
 
blIteratorAPI::blRawArrayWrapper< T >::const_reverse_iterator crbegin () const
 Gives const iterator for beginning reverse iterating over the contiguous memory area of pooled objects, the same area that elems() returns.
 
blIteratorAPI::blRawArrayWrapper< T >::const_reverse_iterator crend () const
 Gives const iterator for ending reverse iterating over the contiguous memory area of pooled objects, the same area that elems() returns.
 
- Public Member Functions inherited from PgeObjectPoolBase
 PgeObjectPoolBase ()=default
 
virtual ~PgeObjectPoolBase ()=default
 
 PgeObjectPoolBase (const PgeObjectPoolBase &)=default
 
PgeObjectPoolBaseoperator= (const PgeObjectPoolBase &)=default
 
 PgeObjectPoolBase (PgeObjectPoolBase &&)=default
 
PgeObjectPoolBaseoperator= (PgeObjectPoolBase &&)=default
 

Static Public Member Functions

static const char * getLoggerModuleName ()
 

Private Attributes

std::string m_name {}
 
size_t m_count {0}
 
size_t m_capacity {0}
 
T * m_pool {nullptr}
 
PgePooledObjectm_firstAvailable {nullptr}
 
blIteratorAPI::blRawArrayWrapper< T > m_rawArrayWrapper
 

Constructor & Destructor Documentation

◆ PgeObjectPool() [1/4]

template<typename T >
PgeObjectPool< T >::PgeObjectPool ( )
inline

This constructor should be used when parameters for initializing the pool is NOT available.

In this case, no memory is allocated, size remains 0, and later the pool needs to be initialized using reserve(). The name of the pool will be "unnamed pool".

Definition at line 236 of file PgeObjectPool.h.

◆ PgeObjectPool() [2/4]

template<typename T >
template<typename... Args>
PgeObjectPool< T >::PgeObjectPool ( const std::string & poolName,
const size_t & capacity,
Args &&... pooledObjArgs )
inline

Not only the memory pool is allocated for all pooled objects, but their non-default constructor is also called with the provided pooled object parameters, or their default constructor if that is available.

It is decided by the user if the pooled object can be properly initialized when the pool is allocated, or further initialization is needed later. In the latter case, either a default constructor must be available or default parameters should be passed to this constructor to be forwarded to the pooled object's non-default constructor to bring the pooled objects to a default state, and later the pooled objects can be properly initialized using the pool's create() function which can forward arbitrary parameters to the pooled object's init() function.

Parameters
poolNameName of this pool, for informative purpose.
capacityNumber of pooled objects to be stored in this pool. Can be changed later with reserve() only if 0 is passed here.
pooledObjArgsArguments to be forwarded to the constructor of the pooled objects.

Definition at line 260 of file PgeObjectPool.h.

◆ ~PgeObjectPool()

template<typename T >
PgeObjectPool< T >::~PgeObjectPool ( )
inline

Definition at line 266 of file PgeObjectPool.h.

◆ PgeObjectPool() [3/4]

template<typename T >
PgeObjectPool< T >::PgeObjectPool ( const PgeObjectPool< T > & )
delete

◆ PgeObjectPool() [4/4]

template<typename T >
PgeObjectPool< T >::PgeObjectPool ( PgeObjectPool< T > && )
delete

Member Function Documentation

◆ begin()

template<typename T >
blIteratorAPI::blRawArrayWrapper< T >::iterator PgeObjectPool< T >::begin ( )
inline

Gives iterator for beginning iterating over the contiguous memory area of pooled objects, the same area that elems() returns.

Note that iterating over this area iterating over both used and non-used pooled objects, thus you should filter for used pooled objects manually.

Returns
Iterator to the first element of the object pool, to begin iterating over elements in order as they are placed in the contiguous memory pool.

Definition at line 556 of file PgeObjectPool.h.

◆ capacity()

template<typename T >
const size_t & PgeObjectPool< T >::capacity ( ) const
inline
Returns
Total number of allocated objects (PgePooledObject) in this pool.

Definition at line 327 of file PgeObjectPool.h.

◆ capacityBytes()

template<typename T >
size_t PgeObjectPool< T >::capacityBytes ( ) const
inline
Returns
Total number of Bytes allocated for the pooled objects (PgePooledObject) in this pool.

Definition at line 335 of file PgeObjectPool.h.

◆ cbegin()

template<typename T >
blIteratorAPI::blRawArrayWrapper< T >::const_iterator PgeObjectPool< T >::cbegin ( ) const
inline

Gives const iterator for beginning iterating over the contiguous memory area of pooled objects, the same area that elems() returns.

Note that iterating over this area iterating over both used and non-used pooled objects, thus you should filter for used pooled objects manually.

Returns
Constant iterator to the first element of the object pool, to begin iterating over elements in order as they are placed in the contiguous memory pool.

Definition at line 578 of file PgeObjectPool.h.

◆ cend()

template<typename T >
blIteratorAPI::blRawArrayWrapper< T >::const_iterator PgeObjectPool< T >::cend ( ) const
inline

Gives const iterator for ending iterating over the contiguous memory area of pooled objects, the same area that elems() returns.

Note that iterating over this area iterating over both used and non-used pooled objects, thus you should filter for used pooled objects manually.

Returns
Constant iterator to after the last element of the object pool, to detect finished iterating over elements in order as they are placed in the contiguous memory pool.

Definition at line 589 of file PgeObjectPool.h.

◆ clear()

template<typename T >
void PgeObjectPool< T >::clear ( )
inline

Resets the free (usable) flag of all objects in the pool, "returns them" into the pool so they can be reused again.

Complexity is O(n) (linear).

Definition at line 516 of file PgeObjectPool.h.

◆ count()

template<typename T >
const size_t & PgeObjectPool< T >::count ( ) const
inline
Returns
Number of used objects (PgePooledObject) in this pool, having their used() state true. Basically this is the number of elements in the container, if this pool was an std container.

Definition at line 308 of file PgeObjectPool.h.

◆ crbegin()

template<typename T >
blIteratorAPI::blRawArrayWrapper< T >::const_reverse_iterator PgeObjectPool< T >::crbegin ( ) const
inline

Gives const iterator for beginning reverse iterating over the contiguous memory area of pooled objects, the same area that elems() returns.

Note that iterating over this area iterating over both used and non-used pooled objects, thus you should filter for used pooled objects manually.

Returns
Constant reverse iterator to the last element of the object pool, to begin iterating over elements in reverse order, from the end of the contiguous memory pool.

Definition at line 622 of file PgeObjectPool.h.

◆ create()

template<typename T >
template<typename... Args>
T * PgeObjectPool< T >::create ( Args &&... pooledObjArgs)
inline

Finds a free (usable) object in the pool, sets it flag as used and returns it.

It also forwards arbitrary parameters to the pooled object's init() function. Complexity is O(1) (constant). Note: the returned object stays in the pool but marked as used, and the user can mark it as free by calling remove().

Returns
An object ready to be used by caller, or nullptr if all objects within the pool are used already.

Definition at line 365 of file PgeObjectPool.h.

◆ crend()

template<typename T >
blIteratorAPI::blRawArrayWrapper< T >::const_reverse_iterator PgeObjectPool< T >::crend ( ) const
inline

Gives const iterator for ending reverse iterating over the contiguous memory area of pooled objects, the same area that elems() returns.

Note that iterating over this area iterating over both used and non-used pooled objects, thus you should filter for used pooled objects manually.

Returns
Constant reverse iterator to after the first element of the object pool, to detect finished iterating over elements in reversed order, from the end of the contiguous memory pool.

Definition at line 633 of file PgeObjectPool.h.

◆ deallocate()

template<typename T >
void PgeObjectPool< T >::deallocate ( )
inline

Frees up the allocated contiguous memory pool, capacity becomes zero, name becomes "unnamed pool".

Capacity can be changed again to non-zero value using reserve().

Definition at line 280 of file PgeObjectPool.h.

◆ elems() [1/2]

template<typename T >
T * PgeObjectPool< T >::elems ( )
inline
Returns
All pooled instances, derived from PgePooledObject, both free and used. Nullptr if the pool is not yet initialized with non-zero size.

Definition at line 528 of file PgeObjectPool.h.

◆ elems() [2/2]

template<typename T >
const T * PgeObjectPool< T >::elems ( ) const
inline
Returns
All pooled instances, derived from PgePooledObject, both free and used. Nullptr if the pool is not yet initialized with non-zero size.

Definition at line 537 of file PgeObjectPool.h.

◆ empty()

template<typename T >
bool PgeObjectPool< T >::empty ( ) const
inline
Returns
True if none of the pooled objects are currently in use, false otherwise.

Definition at line 343 of file PgeObjectPool.h.

◆ end()

template<typename T >
blIteratorAPI::blRawArrayWrapper< T >::iterator PgeObjectPool< T >::end ( )
inline

Gives iterator for ending iterating over the contiguous memory area of pooled objects, the same area that elems() returns.

Note that iterating over this area iterating over both used and non-used pooled objects, thus you should filter for used pooled objects manually.

Returns
Iterator to after the last element of the object pool, to detect finished iterating over elements in order as they are placed in the contiguous memory pool.

Definition at line 567 of file PgeObjectPool.h.

◆ erase()

template<typename T >
blIteratorAPI::blRawArrayWrapper< T >::iterator PgeObjectPool< T >::erase ( typename blIteratorAPI::blRawArrayWrapper< T >::iterator itPos)
inline

Resets the free (usable) flag of the pooled object pointed by the given iterator, "returns" the object into the pool so it can be reused again.

Equivalent to: remove(*itPos). This function is for convenience, to mimic the erase() function of std containers, so it is easier to migrate code using an std::container to use PgeObjectPool. Complexity is O(1) (constant).

Note: the erased object stays in the pool's contiguous memory, just gets marked as free, so a future call to create() might return it again to the user.

Parameters
itPosIterator to the element to be "erased".
Returns
Iterator following the last removed element. If itPos refers to the last element, then the end() iterator is returned.

Definition at line 431 of file PgeObjectPool.h.

◆ getConsole()

template<typename T >
CConsole & PgeObjectPool< T >::getConsole ( ) const
inline

Definition at line 226 of file PgeObjectPool.h.

◆ getLoggerModuleName()

template<typename T >
static const char * PgeObjectPool< T >::getLoggerModuleName ( )
inlinestatic

Definition at line 219 of file PgeObjectPool.h.

◆ name()

template<typename T >
const std::string & PgeObjectPool< T >::name ( ) const
inline
Returns
Name of this pool as it was specified in ctor.

Definition at line 351 of file PgeObjectPool.h.

◆ operator=() [1/2]

template<typename T >
PgeObjectPool & PgeObjectPool< T >::operator= ( const PgeObjectPool< T > & )
delete

◆ operator=() [2/2]

template<typename T >
PgeObjectPool && PgeObjectPool< T >::operator= ( PgeObjectPool< T > && )
delete

◆ rawArrayWrapper()

template<typename T >
blIteratorAPI::blRawArrayWrapper< T > PgeObjectPool< T >::rawArrayWrapper ( )
inline
Returns
The underlying wrapper object giving the iterator functionality.

Definition at line 545 of file PgeObjectPool.h.

◆ rbegin()

template<typename T >
blIteratorAPI::blRawArrayWrapper< T >::reverse_iterator PgeObjectPool< T >::rbegin ( )
inline

Gives iterator for beginning reverse iterating over the contiguous memory area of pooled objects, the same area that elems() returns.

Note that iterating over this area iterating over both used and non-used pooled objects, thus you should filter for used pooled objects manually.

Returns
Reverse iterator to the last element of the object pool, to begin iterating over elements in reverse order, from the end of the contiguous memory pool.

Definition at line 600 of file PgeObjectPool.h.

◆ remove()

template<typename T >
void PgeObjectPool< T >::remove ( PgePooledObject & obj)
inlinevirtual

Resets the free (usable) flag of this object, "returns it" into the pool so it can be reused again.

Complexity is O(1) (constant).

Note: the removed object stays in the pool's contiguous memory, just gets marked as free, so a future call to create() might return it again to the user.

Parameters
objThe pooled object to be returned to the pool as free-to-use object.

Implements PgeObjectPoolBase.

Definition at line 395 of file PgeObjectPool.h.

◆ rend()

template<typename T >
blIteratorAPI::blRawArrayWrapper< T >::reverse_iterator PgeObjectPool< T >::rend ( )
inline

Gives iterator for ending reverse iterating over the contiguous memory area of pooled objects, the same area that elems() returns.

Note that iterating over this area iterating over both used and non-used pooled objects, thus you should filter for used pooled objects manually.

Returns
Reverse iterator to after the first element of the object pool, to detect finished iterating over elements in reversed order, from the end of the contiguous memory pool.

Definition at line 611 of file PgeObjectPool.h.

◆ reserve()

template<typename T >
template<typename... Args>
void PgeObjectPool< T >::reserve ( const std::string & poolName,
const size_t & capacity,
Args &&... pooledObjArgs )
inline

Not only the memory pool is allocated for all pooled objects, but their non-default constructor is also called with the provided pooled object parameters, or their default constructor if that is available.

Currently works only for zero-capacity pools.

Cannot be used to reduce the capacity of the container. To reduce the capacity of a non-zero capacity container to non-zero, or to increase the capacity, first use deallocate() to completely free up the used memory area, and then call reserve().

It is decided by the user if the pooled object can be properly initialized when the pool is allocated, or further initialization is needed later. In the latter case, either a default constructor must be available or default parameters should be passed to this function to be forwarded to the pooled object's non-default constructor to bring the pooled objects to a default state, and later the pooled objects can be properly initialized using the pool's create() function which can forward arbitrary parameters to the pooled objects init() function.

Parameters
poolNameName of this pool, for informative purpose.
capacityNumber of pooled objects to be stored in this pool. Can be changed later only with reserve() if 0 is passed here.
pooledObjArgsArguments to be forwarded to the constructor of the pooled objects.

Definition at line 466 of file PgeObjectPool.h.

◆ size()

template<typename T >
const size_t & PgeObjectPool< T >::size ( ) const
inline

Conventionally std containers have a size() member function returning the number of elements, NOT the capacity.

Thus, size() is equivalent to count().

Returns
Number of used objects (PgePooledObject) in this pool, having their used() state true. Basically this is the number of elements in the container, if this pool was an std container.

Definition at line 319 of file PgeObjectPool.h.

Member Data Documentation

◆ m_capacity

template<typename T >
size_t PgeObjectPool< T >::m_capacity {0}
private

Definition at line 640 of file PgeObjectPool.h.

◆ m_count

template<typename T >
size_t PgeObjectPool< T >::m_count {0}
private

Definition at line 640 of file PgeObjectPool.h.

◆ m_firstAvailable

template<typename T >
PgePooledObject* PgeObjectPool< T >::m_firstAvailable {nullptr}
private

Definition at line 642 of file PgeObjectPool.h.

◆ m_name

template<typename T >
std::string PgeObjectPool< T >::m_name {}
private

Definition at line 639 of file PgeObjectPool.h.

◆ m_pool

template<typename T >
T* PgeObjectPool< T >::m_pool {nullptr}
private

Definition at line 641 of file PgeObjectPool.h.

◆ m_rawArrayWrapper

template<typename T >
blIteratorAPI::blRawArrayWrapper<T> PgeObjectPool< T >::m_rawArrayWrapper
private

Definition at line 643 of file PgeObjectPool.h.


The documentation for this class was generated from the following file: