path end leak

Signed-off-by: James Cherry <cherry@parallaxsw.com>
This commit is contained in:
James Cherry 2026-03-10 10:26:59 -07:00
parent 0850e97b88
commit 2c1024a6bb
3 changed files with 29 additions and 12 deletions

View File

@ -27,6 +27,7 @@
#include <vector>
#include <algorithm>
#include <functional>
#include <optional>
namespace sta {
@ -118,13 +119,14 @@ public:
// If the heap is not full, the element is added.
// If the heap is full and the new element is better than the worst element,
// the worst element is replaced. Otherwise, the element is ignored.
// Returns true if the element was inserted, false if it was ignored.
bool
// Returns (inserted, displaced): inserted is true if the element was inserted,
// displaced is set when an element was pushed out (caller must handle ownership).
std::pair<bool, std::optional<T>>
insert(const T& value) {
if (heap_.size() < max_size_) {
heap_.push_back(value);
std::push_heap(heap_.begin(), heap_.end(), min_heap_comp_);
return true;
return {true, std::nullopt};
}
else if (!heap_.empty()) {
// When keeping N worst (smallest) values: if new value is smaller than worst,
@ -134,23 +136,25 @@ public:
if (comp_(value, heap_.front())) {
// New value is smaller than worst - find and replace the largest element
auto max_it = std::max_element(heap_.begin(), heap_.end(), comp_);
T displaced = std::move(*max_it);
*max_it = value;
// Rebuild heap since we modified an internal element
std::make_heap(heap_.begin(), heap_.end(), min_heap_comp_);
return true;
return {true, std::move(displaced)};
}
// Otherwise, new value is >= worst, so we already have worse values - reject it
}
return false;
return {false, std::nullopt};
}
// Insert an element using move semantics
bool insert(T&& value)
std::pair<bool, std::optional<T>>
insert(T&& value)
{
if (heap_.size() < max_size_) {
heap_.push_back(std::move(value));
std::push_heap(heap_.begin(), heap_.end(), min_heap_comp_);
return true;
return {true, std::nullopt};
}
else if (!heap_.empty()) {
// When keeping N worst (smallest) values: if new value is smaller than worst,
@ -160,14 +164,15 @@ public:
if (comp_(value, heap_.front())) {
// New value is smaller than worst - find and replace the largest element
auto max_it = std::max_element(heap_.begin(), heap_.end(), comp_);
T displaced = std::move(*max_it);
*max_it = std::move(value);
// Rebuild heap since we modified an internal element
std::make_heap(heap_.begin(), heap_.end(), min_heap_comp_);
return true;
return {true, std::move(displaced)};
}
// Otherwise, new value is >= worst, so we already have worse values - reject it
}
return false;
return {false, std::nullopt};
}
// Extract all elements sorted from best to worst.

View File

@ -67,6 +67,7 @@ public:
float min_slack,
float max_slack,
const StaState *sta);
~PathGroup();
const std::string &name() const { return name_; }
const MinMax *minMax() const { return min_max_;}
PathEndSeq pathEnds() const;

View File

@ -105,6 +105,12 @@ PathGroup::PathGroup(const char *name,
{
}
PathGroup::~PathGroup()
{
PathEndSeq path_ends = heap_.extract();
deleteContents(path_ends);
}
PathEndSeq
PathGroup::pathEnds() const
{
@ -170,15 +176,20 @@ void
PathGroup::insert(PathEnd *path_end)
{
LockGuard lock(lock_);
heap_.insert(path_end);
path_end->setPathGroup(this);
auto [inserted, displaced] = heap_.insert(path_end);
if (inserted)
path_end->setPathGroup(this);
else
delete path_end;
if (displaced)
delete *displaced;
}
void
PathGroup::pushEnds(PathEndSeq &path_ends)
{
if (!heap_.empty()) {
PathEndSeq ends = heap_.extract();
PathEndSeq ends = heap_.contents();
path_ends.reserve(path_ends.size() + ends.size());
// Append heap path ends to path_ends.
path_ends.insert(path_ends.end(),