Add ArenaVector
This commit is contained in:
@@ -277,10 +277,14 @@ public:
|
|||||||
* @brief Type-safe version of realloc_raw for arrays of type T.
|
* @brief Type-safe version of realloc_raw for arrays of type T.
|
||||||
*
|
*
|
||||||
* @param ptr Pointer to the existing allocation (must be from this allocator)
|
* @param ptr Pointer to the existing allocation (must be from this allocator)
|
||||||
|
* If nullptr, behaves like allocate<T>(new_size)
|
||||||
* @param old_size Size of the existing allocation in number of T objects
|
* @param old_size Size of the existing allocation in number of T objects
|
||||||
|
* Ignored if ptr is nullptr
|
||||||
* @param new_size Desired new size in number of T objects
|
* @param new_size Desired new size in number of T objects
|
||||||
* @return Pointer to the reallocated memory (may be the same as ptr or
|
* @return Pointer to the reallocated memory (may be the same as ptr or
|
||||||
* different)
|
* different)
|
||||||
|
* @note Follows standard realloc() semantics: realloc(nullptr, size) ==
|
||||||
|
* malloc(size)
|
||||||
* @note Prints error to stderr and calls std::abort() if memory allocation
|
* @note Prints error to stderr and calls std::abort() if memory allocation
|
||||||
* fails or size overflow occurs
|
* fails or size overflow occurs
|
||||||
*/
|
*/
|
||||||
@@ -575,3 +579,44 @@ public:
|
|||||||
|
|
||||||
template <typename U> friend class ArenaStlAllocator;
|
template <typename U> friend class ArenaStlAllocator;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// Simple arena-aware vector that doesn't have a destructor
|
||||||
|
/// Safe to return as span because both the vector and its data are
|
||||||
|
/// arena-allocated Uses arena's realloc() for efficient growth without copying
|
||||||
|
/// when possible
|
||||||
|
template <typename T> struct ArenaVector {
|
||||||
|
explicit ArenaVector(ArenaAllocator *arena)
|
||||||
|
: arena_(arena), data_(nullptr), size_(0), capacity_(0) {}
|
||||||
|
|
||||||
|
void push_back(const T &item) {
|
||||||
|
if (size_ >= capacity_) {
|
||||||
|
grow();
|
||||||
|
}
|
||||||
|
data_[size_++] = item;
|
||||||
|
}
|
||||||
|
|
||||||
|
T *data() { return data_; }
|
||||||
|
const T *data() const { return data_; }
|
||||||
|
size_t size() const { return size_; }
|
||||||
|
bool empty() const { return size_ == 0; }
|
||||||
|
|
||||||
|
T &operator[](size_t index) { return data_[index]; }
|
||||||
|
const T &operator[](size_t index) const { return data_[index]; }
|
||||||
|
|
||||||
|
// No destructor - arena cleanup handles memory
|
||||||
|
|
||||||
|
private:
|
||||||
|
void grow() {
|
||||||
|
size_t new_capacity = capacity_ == 0 ? 8 : capacity_ * 2;
|
||||||
|
|
||||||
|
// arena.realloc() handles nullptr like standard realloc() - acts like
|
||||||
|
// malloc() This avoids copying when growing in-place is possible
|
||||||
|
data_ = arena_->realloc(data_, capacity_, new_capacity);
|
||||||
|
capacity_ = new_capacity;
|
||||||
|
}
|
||||||
|
|
||||||
|
ArenaAllocator *arena_;
|
||||||
|
T *data_;
|
||||||
|
size_t size_;
|
||||||
|
size_t capacity_;
|
||||||
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user