reclaim destroyed arrival arrays

Signed-off-by: James Cherry <cherry@parallaxsw.com>
This commit is contained in:
James Cherry 2021-09-17 15:42:07 -07:00
parent b06e72d61f
commit 2e89d12078
2 changed files with 39 additions and 14 deletions

View File

@ -527,7 +527,7 @@ void
Graph::deleteArrivals(Vertex *vertex, Graph::deleteArrivals(Vertex *vertex,
uint32_t count) uint32_t count)
{ {
arrivals_.deleteArray(count); arrivals_.destroy(vertex->arrivals(), count);
vertex->setArrivals(arrival_null); vertex->setArrivals(arrival_null);
} }
@ -557,7 +557,7 @@ void
Graph::deleteRequireds(Vertex *vertex, Graph::deleteRequireds(Vertex *vertex,
uint32_t count) uint32_t count)
{ {
arrivals_.deleteArray(count); arrivals_.destroy(vertex->requireds(), count);
vertex->setRequireds(arrival_null); vertex->setRequireds(arrival_null);
} }

View File

@ -9,6 +9,7 @@
#pragma once #pragma once
#include <string.h> // memcpy #include <string.h> // memcpy
#include <vector>
#include "ObjectId.hh" #include "ObjectId.hh"
#include "Error.hh" #include "Error.hh"
@ -34,7 +35,8 @@ public:
void make(uint32_t count, void make(uint32_t count,
TYPE *&array, TYPE *&array,
ObjectId &id); ObjectId &id);
void deleteArray(uint32_t count); void destroy(ObjectId id,
uint32_t count);
// Grow as necessary and return pointer for id. // Grow as necessary and return pointer for id.
TYPE *ensureId(ObjectId id); TYPE *ensureId(ObjectId id);
TYPE *pointer(ObjectId id) const; TYPE *pointer(ObjectId id) const;
@ -61,6 +63,8 @@ private:
size_t blocks_capacity_; size_t blocks_capacity_;
ArrayBlock<TYPE>* *blocks_; ArrayBlock<TYPE>* *blocks_;
ArrayBlock<TYPE>* *prev_blocks_; ArrayBlock<TYPE>* *prev_blocks_;
// Linked list of free arrays indexed by array size.
std::vector<ObjectId> free_list_;
static constexpr ObjectId idx_mask_ = block_size - 1; static constexpr ObjectId idx_mask_ = block_size - 1;
}; };
@ -98,17 +102,28 @@ ArrayTable<TYPE>::make(uint32_t count,
TYPE *&array, TYPE *&array,
ObjectId &id) ObjectId &id)
{ {
ArrayBlock<TYPE> *block = blocks_size_ ? blocks_[free_block_idx_] : nullptr; // Check the free list for a previously destroyed array with the right size.
if ((free_idx_ == object_idx_null if (count < free_list_.size()
&& free_block_idx_ == block_idx_null) && free_list_[count] != object_id_null) {
|| free_idx_ + count >= block->size()) { id = free_list_[count];
uint32_t size = (count > block_size) ? count : block_size; array = pointer(id);
block = makeBlock(size);
ObjectId *head = reinterpret_cast<ObjectId*>(array);
free_list_[count] = *head;
}
else {
ArrayBlock<TYPE> *block = blocks_size_ ? blocks_[free_block_idx_] : nullptr;
if ((free_idx_ == object_idx_null
&& free_block_idx_ == block_idx_null)
|| free_idx_ + count >= block->size()) {
uint32_t size = (count > block_size) ? count : block_size;
block = makeBlock(size);
}
// makeId(free_block_idx_, idx_bits)
id = (free_block_idx_ << idx_bits) + free_idx_;
array = block->pointer(free_idx_);
free_idx_ += count;
} }
// makeId(free_block_idx_, idx_bits)
id = (free_block_idx_ << idx_bits) + free_idx_;
array = block->pointer(free_idx_);
free_idx_ += count;
size_ += count; size_ += count;
} }
@ -147,8 +162,17 @@ ArrayTable<TYPE>::pushBlock(ArrayBlock<TYPE> *block)
template <class TYPE> template <class TYPE>
void void
ArrayTable<TYPE>::deleteArray(uint32_t) ArrayTable<TYPE>::destroy(ObjectId id,
uint32_t count)
{ {
if (count >= free_list_.size())
free_list_.resize(count + 1);
TYPE *array = pointer(id);
// Prepend id to the free list.
ObjectId *head = reinterpret_cast<ObjectId*>(array);
*head = free_list_[count];
free_list_[count] = id;
size_ -= count;
} }
template <class TYPE> template <class TYPE>
@ -199,6 +223,7 @@ ArrayTable<TYPE>::clear()
size_ = 0; size_ = 0;
free_block_idx_ = block_idx_null; free_block_idx_ = block_idx_null;
free_idx_ = object_idx_null; free_idx_ = object_idx_null;
free_list_.clear();
} }
//////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////