Uses `quiche::QuicheCircularDeque` as the type backing the pending frame queue, rather than `std::list`.

`QuicheCircularDeque` is much more memory- and CPU-efficient.

Protected by does not affect the GFE2 binary; not protected.

PiperOrigin-RevId: 852538036
diff --git a/quiche/http2/adapter/oghttp2_session.cc b/quiche/http2/adapter/oghttp2_session.cc
index 88eab8e..f345ec7 100644
--- a/quiche/http2/adapter/oghttp2_session.cc
+++ b/quiche/http2/adapter/oghttp2_session.cc
@@ -696,6 +696,10 @@
   // Serialize and send frames in the queue.
   while (!frames_.empty()) {
     const auto& frame_ptr = frames_.front();
+    if (frame_ptr == nullptr) {
+      frames_.pop_front();
+      continue;
+    }
     FrameAttributeCollector c;
     frame_ptr->Visit(&c);
 
@@ -1960,11 +1964,10 @@
     for (auto it = frames_.begin();
          frames_remaining > 0 && it != frames_.end();) {
       if (static_cast<Http2StreamId>((*it)->stream_id()) == stream_id) {
-        it = frames_.erase(it);
+        *it = nullptr;
         --frames_remaining;
-      } else {
-        ++it;
       }
+      ++it;
     }
   }
   if (write_scheduler_.StreamRegistered(stream_id)) {
@@ -2051,9 +2054,11 @@
   // TODO(diannahu): Consider informing the visitor of dropped frames. This may
   // mean keeping the frames and invoking a frame-not-sent callback, similar to
   // nghttp2. Could add a closure to each frame in the frames queue.
-  frames_.remove_if([](const auto& frame) {
-    return frame->frame_type() != spdy::SpdyFrameType::RST_STREAM;
-  });
+  for (std::unique_ptr<spdy::SpdyFrameIR>& frame : frames_) {
+    if (frame->frame_type() != spdy::SpdyFrameType::RST_STREAM) {
+      frame = nullptr;
+    }
+  };
 
   if (initial_settings != nullptr) {
     frames_.push_front(std::move(initial_settings));
diff --git a/quiche/http2/adapter/oghttp2_session.h b/quiche/http2/adapter/oghttp2_session.h
index 19d3545..b788cb0 100644
--- a/quiche/http2/adapter/oghttp2_session.h
+++ b/quiche/http2/adapter/oghttp2_session.h
@@ -508,8 +508,9 @@
   quiche::QuicheLinkedHashMap<Http2StreamId, PendingStreamState>
       pending_streams_;
 
-  // The queue of outbound frames.
-  std::list<std::unique_ptr<spdy::SpdyFrameIR>> frames_;
+  // The queue of outbound frames. May contain nullptr entries for frames that
+  // have been removed from the queue.
+  quiche::QuicheCircularDeque<std::unique_ptr<spdy::SpdyFrameIR>> frames_;
   // Buffered data (connection preface, serialized frames) that has not yet been
   // sent.
   ChunkedBuffer buffered_data_;