Provide absl::Span<QuicMemSlice> version of WriteMemSlices() The goal is to eventually deprecate QuicMemSliceSpan, thus reducing the amount of platform code we need to carry around. PiperOrigin-RevId: 378444535
diff --git a/quic/core/quic_stream.cc b/quic/core/quic_stream.cc index 3f1b7d9..9744ed3 100644 --- a/quic/core/quic_stream.cc +++ b/quic/core/quic_stream.cc
@@ -19,6 +19,7 @@ #include "quic/platform/api/quic_flag_utils.h" #include "quic/platform/api/quic_flags.h" #include "quic/platform/api/quic_logging.h" +#include "quic/platform/api/quic_mem_slice.h" using spdy::SpdyPriority; @@ -759,6 +760,16 @@ } QuicConsumedData QuicStream::WriteMemSlices(QuicMemSliceSpan span, bool fin) { + return WriteMemSlicesInner(MemSliceSpanWrapper(span), fin); +} + +QuicConsumedData QuicStream::WriteMemSlices(absl::Span<QuicMemSlice> span, + bool fin) { + return WriteMemSlicesInner(MemSliceSpanWrapper(span), fin); +} + +QuicConsumedData QuicStream::WriteMemSlicesInner(MemSliceSpanWrapper span, + bool fin) { QuicConsumedData consumed_data(0, false); if (span.empty() && !fin) { QUIC_BUG(quic_bug_10586_6) << "span.empty() && !fin"; @@ -786,7 +797,7 @@ if (!span.empty()) { // Buffer all data if buffered data size is below limit. QuicStreamOffset offset = send_buffer_.stream_offset(); - consumed_data.bytes_consumed = send_buffer_.SaveMemSliceSpan(span); + consumed_data.bytes_consumed = span.SaveTo(send_buffer_); if (offset > send_buffer_.stream_offset() || kMaxStreamLength < send_buffer_.stream_offset()) { QUIC_BUG(quic_bug_10586_8) << "Write too many data via stream " << id_;
diff --git a/quic/core/quic_stream.h b/quic/core/quic_stream.h index 6e6e623..ca20eb4 100644 --- a/quic/core/quic_stream.h +++ b/quic/core/quic_stream.h
@@ -24,6 +24,7 @@ #include "absl/strings/string_view.h" #include "absl/types/optional.h" +#include "absl/types/span.h" #include "quic/core/quic_flow_controller.h" #include "quic/core/quic_packets.h" #include "quic/core/quic_stream_send_buffer.h" @@ -32,6 +33,7 @@ #include "quic/core/session_notifier_interface.h" #include "quic/core/stream_delegate_interface.h" #include "quic/platform/api/quic_export.h" +#include "quic/platform/api/quic_mem_slice.h" #include "quic/platform/api/quic_mem_slice_span.h" #include "quic/platform/api/quic_reference_counted.h" #include "spdy/core/spdy_protocol.h" @@ -343,9 +345,13 @@ // succeeds. bool MaybeSetTtl(QuicTime::Delta ttl); - // Same as WritevData except data is provided in reference counted memory so - // that data copy is avoided. + // Commits data into the stream write buffer, and potentially sends it over + // the wire. This method has all-or-nothing semantics: if the write buffer is + // not full, all of the memslices in |span| are moved into it; otherwise, + // nothing happens. + // TODO(vasilvv): deprecate and remove QuicMemSliceSpan version. QuicConsumedData WriteMemSlices(QuicMemSliceSpan span, bool fin); + QuicConsumedData WriteMemSlices(absl::Span<QuicMemSlice> span, bool fin); // Returns true if any stream data is lost (including fin) and needs to be // retransmitted. @@ -464,6 +470,26 @@ friend class test::QuicStreamPeer; friend class QuicStreamUtils; + // Wraps around either QuicMemSliceSpan or absl::Span<QuicMemSlice>. + // TODO(vasilvv): delete this after QuicMemSliceSpan is gone. + class QUIC_EXPORT_PRIVATE MemSliceSpanWrapper { + public: + explicit MemSliceSpanWrapper(QuicMemSliceSpan span) : old_(span) {} + explicit MemSliceSpanWrapper(absl::Span<QuicMemSlice> span) : new_(span) {} + + bool empty() { return old_.has_value() ? old_->empty() : new_.empty(); } + size_t SaveTo(QuicStreamSendBuffer& send_buffer) { + if (old_.has_value()) { + return send_buffer.SaveMemSliceSpan(*old_); + } + return send_buffer.SaveMemSliceSpan(new_); + } + + private: + absl::optional<QuicMemSliceSpan> old_; + absl::Span<QuicMemSlice> new_; + }; + QuicStream(QuicStreamId id, QuicSession* session, QuicStreamSequencer sequencer, @@ -502,6 +528,8 @@ // Returns true if deadline_ has passed. bool HasDeadlinePassed() const; + QuicConsumedData WriteMemSlicesInner(MemSliceSpanWrapper span, bool fin); + QuicStreamSequencer sequencer_; QuicStreamId id_; // Pointer to the owning QuicSession object.
diff --git a/quic/core/quic_stream_send_buffer.cc b/quic/core/quic_stream_send_buffer.cc index 3b1b37b..1e32e54 100644 --- a/quic/core/quic_stream_send_buffer.cc +++ b/quic/core/quic_stream_send_buffer.cc
@@ -12,6 +12,7 @@ #include "quic/platform/api/quic_flag_utils.h" #include "quic/platform/api/quic_flags.h" #include "quic/platform/api/quic_logging.h" +#include "quic/platform/api/quic_mem_slice.h" namespace quic { @@ -96,6 +97,20 @@ [&](QuicMemSlice slice) { SaveMemSlice(std::move(slice)); }); } +QuicByteCount QuicStreamSendBuffer::SaveMemSliceSpan( + absl::Span<QuicMemSlice> span) { + QuicByteCount total = 0; + for (QuicMemSlice& slice : span) { + if (slice.length() == 0) { + // Skip empty slices. + continue; + } + total += slice.length(); + SaveMemSlice(std::move(slice)); + } + return total; +} + void QuicStreamSendBuffer::OnStreamDataConsumed(size_t bytes_consumed) { stream_bytes_written_ += bytes_consumed; stream_bytes_outstanding_ += bytes_consumed;
diff --git a/quic/core/quic_stream_send_buffer.h b/quic/core/quic_stream_send_buffer.h index 4b23d3d..f91e476 100644 --- a/quic/core/quic_stream_send_buffer.h +++ b/quic/core/quic_stream_send_buffer.h
@@ -5,6 +5,7 @@ #ifndef QUICHE_QUIC_CORE_QUIC_STREAM_SEND_BUFFER_H_ #define QUICHE_QUIC_CORE_QUIC_STREAM_SEND_BUFFER_H_ +#include "absl/types/span.h" #include "quic/core/frames/quic_stream_frame.h" #include "quic/core/quic_interval_deque.h" #include "quic/core/quic_interval_set.h" @@ -80,6 +81,7 @@ // Save all slices in |span| to send buffer. Return total bytes saved. QuicByteCount SaveMemSliceSpan(QuicMemSliceSpan span); + QuicByteCount SaveMemSliceSpan(absl::Span<QuicMemSlice> span); // Called when |bytes_consumed| bytes has been consumed by the stream. void OnStreamDataConsumed(size_t bytes_consumed);
diff --git a/quic/core/quic_stream_test.cc b/quic/core/quic_stream_test.cc index 2d3298b..e69b657 100644 --- a/quic/core/quic_stream_test.cc +++ b/quic/core/quic_stream_test.cc
@@ -1178,14 +1178,17 @@ SetQuicFlag(FLAGS_quic_buffered_data_threshold, 100); Initialize(); - char data[1024]; - std::vector<std::pair<char*, size_t>> buffers; - buffers.push_back(std::make_pair(data, ABSL_ARRAYSIZE(data))); - buffers.push_back(std::make_pair(data, ABSL_ARRAYSIZE(data))); - QuicTestMemSliceVector vector1(buffers); - QuicTestMemSliceVector vector2(buffers); - QuicMemSliceSpan span1 = vector1.span(); - QuicMemSliceSpan span2 = vector2.span(); + constexpr QuicByteCount kDataSize = 1024; + QuicBufferAllocator* allocator = + connection_->helper()->GetStreamSendBufferAllocator(); + std::vector<QuicMemSlice> vector1; + vector1.push_back(QuicMemSlice(QuicBuffer(allocator, kDataSize))); + vector1.push_back(QuicMemSlice(QuicBuffer(allocator, kDataSize))); + std::vector<QuicMemSlice> vector2; + vector2.push_back(QuicMemSlice(QuicBuffer(allocator, kDataSize))); + vector2.push_back(QuicMemSlice(QuicBuffer(allocator, kDataSize))); + absl::Span<QuicMemSlice> span1(vector1); + absl::Span<QuicMemSlice> span2(vector2); EXPECT_CALL(*session_, WritevData(_, _, _, _, _, _)) .WillOnce(InvokeWithoutArgs([this]() { @@ -1196,7 +1199,7 @@ QuicConsumedData consumed = stream_->WriteMemSlices(span1, false); EXPECT_EQ(2048u, consumed.bytes_consumed); EXPECT_FALSE(consumed.fin_consumed); - EXPECT_EQ(2 * ABSL_ARRAYSIZE(data) - 100, stream_->BufferedDataBytes()); + EXPECT_EQ(2 * kDataSize - 100, stream_->BufferedDataBytes()); EXPECT_FALSE(stream_->fin_buffered()); EXPECT_CALL(*session_, WritevData(_, _, _, _, _, _)).Times(0); @@ -1204,12 +1207,11 @@ consumed = stream_->WriteMemSlices(span2, true); EXPECT_EQ(0u, consumed.bytes_consumed); EXPECT_FALSE(consumed.fin_consumed); - EXPECT_EQ(2 * ABSL_ARRAYSIZE(data) - 100, stream_->BufferedDataBytes()); + EXPECT_EQ(2 * kDataSize - 100, stream_->BufferedDataBytes()); EXPECT_FALSE(stream_->fin_buffered()); QuicByteCount data_to_write = - 2 * ABSL_ARRAYSIZE(data) - 100 - - GetQuicFlag(FLAGS_quic_buffered_data_threshold) + 1; + 2 * kDataSize - 100 - GetQuicFlag(FLAGS_quic_buffered_data_threshold) + 1; EXPECT_CALL(*session_, WritevData(_, _, _, _, _, _)) .WillOnce(InvokeWithoutArgs([this, data_to_write]() { return session_->ConsumeData(stream_->id(), data_to_write, 100u, NO_FIN, @@ -1225,8 +1227,7 @@ consumed = stream_->WriteMemSlices(span2, true); EXPECT_EQ(2048u, consumed.bytes_consumed); EXPECT_TRUE(consumed.fin_consumed); - EXPECT_EQ(2 * ABSL_ARRAYSIZE(data) + - GetQuicFlag(FLAGS_quic_buffered_data_threshold) - 1, + EXPECT_EQ(2 * kDataSize + GetQuicFlag(FLAGS_quic_buffered_data_threshold) - 1, stream_->BufferedDataBytes()); EXPECT_TRUE(stream_->fin_buffered());