diff options
Diffstat (limited to 'Runtime/Utilities/dynamic_block_vector.h')
-rw-r--r-- | Runtime/Utilities/dynamic_block_vector.h | 135 |
1 files changed, 135 insertions, 0 deletions
diff --git a/Runtime/Utilities/dynamic_block_vector.h b/Runtime/Utilities/dynamic_block_vector.h new file mode 100644 index 0000000..302847b --- /dev/null +++ b/Runtime/Utilities/dynamic_block_vector.h @@ -0,0 +1,135 @@ +#pragma once + +#include "Runtime/Allocator/MemoryMacros.h" +#include "Runtime/Utilities/dynamic_array.h" + +// dynamic_block_vector +// +// Allocates dynamic_arrays to hold the data in small blocks. +// Growing pushbacks allocates one new block at a time. +// Calls inplace constructor on all elements, and destroys the elements when removing from the list +// Resize preserves the elements in the list and pushes default initialized elements to reach size +// If resizing to something smaller, elements are popped (and destroyed) from the vector + + +template <typename T> +struct dynamic_block_vector +{ +private: + typedef dynamic_array<T> internal_container; + typedef dynamic_array<internal_container*> container; + +public: + + dynamic_block_vector (size_t allocationBlockSize) + : m_blockSize(allocationBlockSize), m_size(0), m_label(kMemDynamicArrayId, GET_CURRENT_ALLOC_ROOT_HEADER()) + { + } + + dynamic_block_vector (size_t allocationBlockSize, MemLabelId label) + : m_blockSize(allocationBlockSize), m_size(0), m_label(label) + { + } + + dynamic_block_vector (const dynamic_block_vector& rhs) + : m_blockSize(rhs.m_blockSize), m_size(0), m_label(rhs.m_label) + { + *this = rhs; + } + + ~dynamic_block_vector () + { + clear(); + } + + void clear() + { + for(int i = 0; i < m_size; i++) + (*this)[i].~T(); + + for(int i = 0; i < m_data.size(); i++) + UNITY_DELETE(m_data[i],m_label); + + m_data.clear(); + m_size = 0; + } + + void resize (size_t size) + { + while (m_size < size) + push_back(); + while (m_size > size) + pop_back(); + } + + dynamic_block_vector& operator=(const dynamic_block_vector& other) + { + if(this == &other) + return *this; + + clear(); + for( int i = 0; i < other.size(); i++) + push_back(other[i]); + return *this; + } + + template<class Iter> + void assign (Iter first, Iter last) + { + clear(); + for( ; first != last; ++first) + push_back(*first); + } + + void push_back () + { + int outerindex = m_size/m_blockSize; + int innerindex = m_size%m_blockSize; + if(outerindex == m_data.size()) + { + m_data.push_back(UNITY_NEW(internal_container,m_label)(m_blockSize,m_label)); + } + new (&(*m_data[outerindex])[innerindex]) T(); + m_size++; + } + + void push_back (const T& t) + { + int outerindex = m_size/m_blockSize; + int innerindex = m_size%m_blockSize; + if(outerindex == m_data.size()) + { + m_data.push_back(UNITY_NEW(internal_container,m_label)(m_blockSize,m_label)); + } + new (&(*m_data[outerindex])[innerindex]) T(t); + m_size++; + } + + void pop_back () + { + (*this)[m_size-1].~T(); + m_size--; + int outersize = m_size/m_blockSize + 1; + if (outersize < m_data.size()) + { + UNITY_DELETE(m_data.back(),m_label); + m_data.pop_back(); + } + } + + size_t size () const { return m_size; } + + T& back() { Assert (m_size != 0); return (*this)[m_size - 1]; } + + T const& operator[] (size_t index) const { DebugAssert(index < m_size); return (*m_data[index/m_blockSize])[index%m_blockSize]; } + T& operator[] (size_t index) { DebugAssert(index < m_size); return (*m_data[index/m_blockSize])[index%m_blockSize]; } + +private: + + container m_data; + MemLabelId m_label; + size_t m_size; + size_t m_blockSize; +}; + + |