diff --git a/include/sta/BoundedHeap.hh b/include/sta/BoundedHeap.hh index af934e0c..676c1e39 100644 --- a/include/sta/BoundedHeap.hh +++ b/include/sta/BoundedHeap.hh @@ -27,6 +27,7 @@ #include #include #include +#include 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> 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> + 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. diff --git a/include/sta/PathGroup.hh b/include/sta/PathGroup.hh index 03bcb0c5..f71b9f38 100644 --- a/include/sta/PathGroup.hh +++ b/include/sta/PathGroup.hh @@ -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; diff --git a/search/PathGroup.cc b/search/PathGroup.cc index 1fb9e4ea..7a5ccd33 100644 --- a/search/PathGroup.cc +++ b/search/PathGroup.cc @@ -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(),