Change QpackHeaderTable::observer_ type and swap RegisterObserver() argument order. No functional change, prework for fixing a crasher. The motivation for moving away from std::priority is that it does not allow deletion of random elements. gfe-relnote: n/a, change to QUIC v99-only code. Protected by existing disabled gfe2_reloadable_flag_quic_enable_version_99. PiperOrigin-RevId: 272559408 Change-Id: I3f18909201e218627eee3638249aea007b317cd1
diff --git a/quic/core/qpack/qpack_header_table.cc b/quic/core/qpack/qpack_header_table.cc index bb28f72..30f15a5 100644 --- a/quic/core/qpack/qpack_header_table.cc +++ b/quic/core/qpack/qpack_header_table.cc
@@ -131,10 +131,13 @@ } // Notify and deregister observers whose threshold is met, if any. - while (!observers_.empty() && - observers_.top().required_insert_count <= inserted_entry_count()) { - Observer* observer = observers_.top().observer; - observers_.pop(); + while (!observers_.empty()) { + auto it = observers_.begin(); + if (it->first > inserted_entry_count()) { + break; + } + Observer* observer = it->second; + observers_.erase(it); observer->OnInsertCountReachedThreshold(); } @@ -188,10 +191,10 @@ max_entries_ = maximum_dynamic_table_capacity / 32; } -void QpackHeaderTable::RegisterObserver(Observer* observer, - uint64_t required_insert_count) { +void QpackHeaderTable::RegisterObserver(uint64_t required_insert_count, + Observer* observer) { DCHECK_GT(required_insert_count, 0u); - observers_.push({observer, required_insert_count}); + observers_.insert({required_insert_count, observer}); } uint64_t QpackHeaderTable::draining_index(float draining_fraction) const { @@ -219,11 +222,6 @@ return it->InsertionIndex(); } -bool QpackHeaderTable::ObserverWithThreshold::operator>( - const ObserverWithThreshold& other) const { - return required_insert_count > other.required_insert_count; -} - void QpackHeaderTable::EvictDownToCurrentCapacity() { while (dynamic_table_size_ > dynamic_table_capacity_) { DCHECK(!dynamic_entries_.empty());
diff --git a/quic/core/qpack/qpack_header_table.h b/quic/core/qpack/qpack_header_table.h index f251894..919a4eb 100644 --- a/quic/core/qpack/qpack_header_table.h +++ b/quic/core/qpack/qpack_header_table.h
@@ -96,8 +96,8 @@ // Register an observer to be notified when inserted_entry_count() reaches // |required_insert_count|. After the notification, |observer| automatically - // gets unregistered. - void RegisterObserver(Observer* observer, uint64_t required_insert_count); + // gets unregistered. Each observer must only be registered at most once. + void RegisterObserver(uint64_t required_insert_count, Observer* observer); // Used on request streams to encode and decode Required Insert Count. uint64_t max_entries() const { return max_entries_; } @@ -179,21 +179,8 @@ // The number of entries dropped from the dynamic table. uint64_t dropped_entry_count_; - // Data structure to hold an Observer and its threshold. - struct ObserverWithThreshold { - Observer* observer; - uint64_t required_insert_count; - bool operator>(const ObserverWithThreshold& other) const; - }; - - // Use std::greater so that entry with smallest |required_insert_count| - // is on top. - using ObserverHeap = std::priority_queue<ObserverWithThreshold, - std::vector<ObserverWithThreshold>, - std::greater<ObserverWithThreshold>>; - - // Observers waiting to be notified. - ObserverHeap observers_; + // Observers waiting to be notified, sorted by required insert count. + std::multimap<uint64_t, Observer*> observers_; }; } // namespace quic
diff --git a/quic/core/qpack/qpack_header_table_test.cc b/quic/core/qpack/qpack_header_table_test.cc index 00f36e5..5a97c20 100644 --- a/quic/core/qpack/qpack_header_table_test.cc +++ b/quic/core/qpack/qpack_header_table_test.cc
@@ -89,9 +89,9 @@ return table_.SetDynamicTableCapacity(capacity); } - void RegisterObserver(QpackHeaderTable::Observer* observer, - uint64_t required_insert_count) { - table_.RegisterObserver(observer, required_insert_count); + void RegisterObserver(uint64_t required_insert_count, + QpackHeaderTable::Observer* observer) { + table_.RegisterObserver(required_insert_count, observer); } uint64_t max_entries() const { return table_.max_entries(); } @@ -418,7 +418,7 @@ TEST_F(QpackHeaderTableTest, Observer) { StrictMock<MockObserver> observer1; - RegisterObserver(&observer1, 1); + RegisterObserver(1, &observer1); EXPECT_CALL(observer1, OnInsertCountReachedThreshold); InsertEntry("foo", "bar"); EXPECT_EQ(1u, inserted_entry_count()); @@ -427,8 +427,8 @@ // Registration order does not matter. StrictMock<MockObserver> observer2; StrictMock<MockObserver> observer3; - RegisterObserver(&observer3, 3); - RegisterObserver(&observer2, 2); + RegisterObserver(3, &observer3); + RegisterObserver(2, &observer2); EXPECT_CALL(observer2, OnInsertCountReachedThreshold); InsertEntry("foo", "bar"); @@ -444,8 +444,8 @@ // notified. StrictMock<MockObserver> observer4; StrictMock<MockObserver> observer5; - RegisterObserver(&observer4, 4); - RegisterObserver(&observer5, 4); + RegisterObserver(4, &observer4); + RegisterObserver(4, &observer5); EXPECT_CALL(observer4, OnInsertCountReachedThreshold); EXPECT_CALL(observer5, OnInsertCountReachedThreshold);
diff --git a/quic/core/qpack/qpack_progressive_decoder.cc b/quic/core/qpack/qpack_progressive_decoder.cc index 5ce0612..5632286 100644 --- a/quic/core/qpack/qpack_progressive_decoder.cc +++ b/quic/core/qpack/qpack_progressive_decoder.cc
@@ -295,7 +295,7 @@ OnError("Limit on number of blocked streams exceeded."); return false; } - header_table_->RegisterObserver(this, required_insert_count_); + header_table_->RegisterObserver(required_insert_count_, this); } return true;