Remove WriteScheduler interface. It only has one implementations and there are no plans to add any more. PiperOrigin-RevId: 499875408
diff --git a/build/source_list.bzl b/build/source_list.bzl index f43b662..1a6277f 100644 --- a/build/source_list.bzl +++ b/build/source_list.bzl
@@ -75,7 +75,6 @@ "http2/adapter/window_manager.h", "http2/core/http2_trace_logging.h", "http2/core/priority_write_scheduler.h", - "http2/core/write_scheduler.h", "http2/decoder/decode_buffer.h", "http2/decoder/decode_http2_structures.h", "http2/decoder/decode_status.h",
diff --git a/build/source_list.gni b/build/source_list.gni index 60ff738..99ebb16 100644 --- a/build/source_list.gni +++ b/build/source_list.gni
@@ -75,7 +75,6 @@ "src/quiche/http2/adapter/window_manager.h", "src/quiche/http2/core/http2_trace_logging.h", "src/quiche/http2/core/priority_write_scheduler.h", - "src/quiche/http2/core/write_scheduler.h", "src/quiche/http2/decoder/decode_buffer.h", "src/quiche/http2/decoder/decode_http2_structures.h", "src/quiche/http2/decoder/decode_status.h",
diff --git a/build/source_list.json b/build/source_list.json index c8683c8..10b5cd5 100644 --- a/build/source_list.json +++ b/build/source_list.json
@@ -74,7 +74,6 @@ "quiche/http2/adapter/window_manager.h", "quiche/http2/core/http2_trace_logging.h", "quiche/http2/core/priority_write_scheduler.h", - "quiche/http2/core/write_scheduler.h", "quiche/http2/decoder/decode_buffer.h", "quiche/http2/decoder/decode_http2_structures.h", "quiche/http2/decoder/decode_status.h",
diff --git a/quiche/http2/core/priority_write_scheduler.h b/quiche/http2/core/priority_write_scheduler.h index 6f7b92f..1c3820d 100644 --- a/quiche/http2/core/priority_write_scheduler.h +++ b/quiche/http2/core/priority_write_scheduler.h
@@ -16,7 +16,6 @@ #include "absl/container/flat_hash_map.h" #include "absl/strings/str_cat.h" -#include "quiche/http2/core/write_scheduler.h" #include "quiche/common/platform/api/quiche_bug_tracker.h" #include "quiche/common/platform/api/quiche_export.h" #include "quiche/common/platform/api/quiche_logging.h" @@ -30,23 +29,32 @@ class PriorityWriteSchedulerPeer; } -// WriteScheduler implementation that manages the order in which streams are -// written using the SPDY priority scheme described at: -// https://www.chromium.org/spdy/spdy-protocol/spdy-protocol-draft3-1#TOC-2.3.3-Stream-priority +// PriorityWriteScheduler manages the order in which HTTP/2 or HTTP/3 streams +// are written. Each stream has a priority, which is an integer between 0 and 7. +// Higher priority (lower integer value) streams are always given precedence +// over lower priority (higher value) streams, as long as the higher priority +// stream is not blocked. // -// Internally, PriorityWriteScheduler consists of 8 PriorityInfo objects, one -// for each priority value. Each PriorityInfo contains a list of streams of -// that priority that are ready to write, as well as a timestamp of the last -// I/O event that occurred for a stream of that priority. +// Each stream can be in one of two states: ready or not ready (for writing). +// Ready state is changed by calling the MarkStreamReady() and +// MarkStreamNotReady() methods. Only streams in the ready state can be returned +// by PopNextReadyStream(). When returned by that method, the stream's state +// changes to not ready. // template <typename StreamIdType> -class QUICHE_EXPORT PriorityWriteScheduler - : public WriteScheduler<StreamIdType> { +class QUICHE_EXPORT PriorityWriteScheduler { public: - using typename WriteScheduler<StreamIdType>::StreamPrecedenceType; + using StreamPrecedenceType = spdy::StreamPrecedence<StreamIdType>; + // Registers new stream `stream_id` with the scheduler, assigning it the + // given precedence. If the scheduler supports stream dependencies, the + // stream is inserted into the dependency tree under + // `precedence.parent_id()`. + // + // Preconditions: `stream_id` should be unregistered, and + // `precedence.parent_id()` should be registered or `kHttp2RootStreamId`. void RegisterStream(StreamIdType stream_id, - const StreamPrecedenceType& precedence) override { + const StreamPrecedenceType& precedence) { auto stream_info = std::make_unique<StreamInfo>( StreamInfo{precedence.spdy3_priority(), stream_id, false}); bool inserted = @@ -56,7 +64,11 @@ << "Stream " << stream_id << " already registered"; } - void UnregisterStream(StreamIdType stream_id) override { + // Unregisters the given stream from the scheduler, which will no longer keep + // state for it. + // + // Preconditions: `stream_id` should be registered. + void UnregisterStream(StreamIdType stream_id) { auto it = stream_infos_.find(stream_id); if (it == stream_infos_.end()) { QUICHE_BUG(spdy_bug_19_3) << "Stream " << stream_id << " not registered"; @@ -71,12 +83,18 @@ stream_infos_.erase(it); } - bool StreamRegistered(StreamIdType stream_id) const override { + // Returns true if the given stream is currently registered. + bool StreamRegistered(StreamIdType stream_id) const { return stream_infos_.find(stream_id) != stream_infos_.end(); } - StreamPrecedenceType GetStreamPrecedence( - StreamIdType stream_id) const override { + // Returns the precedence of the specified stream. If the scheduler supports + // stream dependencies, calling `parent_id()` on the return value returns the + // stream's parent, and calling `exclusive()` returns true iff the specified + // stream is an only child of the parent stream. + // + // Preconditions: `stream_id` should be registered. + StreamPrecedenceType GetStreamPrecedence(StreamIdType stream_id) const { auto it = stream_infos_.find(stream_id); if (it == stream_infos_.end()) { QUICHE_DVLOG(1) << "Stream " << stream_id << " not registered"; @@ -85,8 +103,14 @@ return StreamPrecedenceType(it->second->priority); } + // Updates the precedence of the given stream. If the scheduler supports + // stream dependencies, `stream_id`'s parent will be updated to be + // `precedence.parent_id()` if it is not already. + // + // Preconditions: `stream_id` should be unregistered, and + // `precedence.parent_id()` should be registered or `kHttp2RootStreamId`. void UpdateStreamPrecedence(StreamIdType stream_id, - const StreamPrecedenceType& precedence) override { + const StreamPrecedenceType& precedence) { auto it = stream_infos_.find(stream_id); if (it == stream_infos_.end()) { // TODO(mpw): add to stream_infos_ on demand--see b/15676312. @@ -108,13 +132,20 @@ stream_info->priority = new_priority; } + // Returns child streams of the given stream, if any. If the scheduler + // doesn't support stream dependencies, returns an empty vector. + // + // Preconditions: `stream_id` should be registered. std::vector<StreamIdType> GetStreamChildren( - StreamIdType /*stream_id*/) const override { + StreamIdType /*stream_id*/) const { return std::vector<StreamIdType>(); } - void RecordStreamEventTime(StreamIdType stream_id, - int64_t now_in_usec) override { + // Records time (in microseconds) of a read/write event for the given + // stream. + // + // Preconditions: `stream_id` should be registered. + void RecordStreamEventTime(StreamIdType stream_id, int64_t now_in_usec) { auto it = stream_infos_.find(stream_id); if (it == stream_infos_.end()) { QUICHE_BUG(spdy_bug_19_4) << "Stream " << stream_id << " not registered"; @@ -125,7 +156,12 @@ std::max(priority_info.last_event_time_usec, now_in_usec); } - int64_t GetLatestEventWithPrecedence(StreamIdType stream_id) const override { + // Returns time (in microseconds) of the last read/write event for a stream + // with higher priority than the priority of the given stream, or 0 if there + // is no such event. + // + // Preconditions: `stream_id` should be registered. + int64_t GetLatestEventWithPrecedence(StreamIdType stream_id) const { auto it = stream_infos_.find(stream_id); if (it == stream_infos_.end()) { QUICHE_BUG(spdy_bug_19_5) << "Stream " << stream_id << " not registered"; @@ -141,13 +177,22 @@ return last_event_time_usec; } - StreamIdType PopNextReadyStream() override { + // If the scheduler has any ready streams, returns the next scheduled + // ready stream, in the process transitioning the stream from ready to not + // ready. + // + // Preconditions: `HasReadyStreams() == true` + StreamIdType PopNextReadyStream() { return std::get<0>(PopNextReadyStreamAndPrecedence()); } - // Returns the next ready stream and its precedence. + // If the scheduler has any ready streams, returns the next scheduled + // ready stream and its priority, in the process transitioning the stream from + // ready to not ready. + // + // Preconditions: `HasReadyStreams() == true` std::tuple<StreamIdType, StreamPrecedenceType> - PopNextReadyStreamAndPrecedence() override { + PopNextReadyStreamAndPrecedence() { for (spdy::SpdyPriority p = spdy::kV3HighestPriority; p <= spdy::kV3LowestPriority; ++p) { ReadyList& ready_list = priority_infos_[p].ready_list; @@ -167,7 +212,12 @@ return std::make_tuple(0, StreamPrecedenceType(spdy::kV3LowestPriority)); } - bool ShouldYield(StreamIdType stream_id) const override { + // Returns true if there's another stream ahead of the given stream in the + // scheduling queue. This function can be called to see if the given stream + // should yield work to another stream. + // + // Preconditions: `stream_id` should be registered. + bool ShouldYield(StreamIdType stream_id) const { auto it = stream_infos_.find(stream_id); if (it == stream_infos_.end()) { QUICHE_BUG(spdy_bug_19_7) << "Stream " << stream_id << " not registered"; @@ -195,7 +245,12 @@ return true; } - void MarkStreamReady(StreamIdType stream_id, bool add_to_front) override { + // Marks the stream as ready to write. If the stream was already ready, does + // nothing. If add_to_front is true, the stream is scheduled ahead of other + // streams of the same priority/weight, otherwise it is scheduled behind them. + // + // Preconditions: `stream_id` should be registered. + void MarkStreamReady(StreamIdType stream_id, bool add_to_front) { auto it = stream_infos_.find(stream_id); if (it == stream_infos_.end()) { QUICHE_BUG(spdy_bug_19_8) << "Stream " << stream_id << " not registered"; @@ -215,7 +270,11 @@ stream_info->ready = true; } - void MarkStreamNotReady(StreamIdType stream_id) override { + // Marks the stream as not ready to write. If the stream is not registered or + // not ready, does nothing. + // + // Preconditions: `stream_id` should be registered. + void MarkStreamNotReady(StreamIdType stream_id) { auto it = stream_infos_.find(stream_id); if (it == stream_infos_.end()) { QUICHE_BUG(spdy_bug_19_9) << "Stream " << stream_id << " not registered"; @@ -231,22 +290,24 @@ stream_info->ready = false; } - // Returns true iff the number of ready streams is non-zero. - bool HasReadyStreams() const override { return num_ready_streams_ > 0; } + // Returns true iff the scheduler has any ready streams. + bool HasReadyStreams() const { return num_ready_streams_ > 0; } - // Returns the number of ready streams. - size_t NumReadyStreams() const override { return num_ready_streams_; } + // Returns the number of streams currently marked ready. + size_t NumReadyStreams() const { return num_ready_streams_; } - size_t NumRegisteredStreams() const override { return stream_infos_.size(); } + // Returns the number of registered streams. + size_t NumRegisteredStreams() const { return stream_infos_.size(); } - std::string DebugString() const override { + // Returns summary of internal state, for logging/debugging. + std::string DebugString() const { return absl::StrCat( "PriorityWriteScheduler {num_streams=", stream_infos_.size(), " num_ready_streams=", NumReadyStreams(), "}"); } - // Returns true if a stream is ready. - bool IsStreamReady(StreamIdType stream_id) const override { + // Returns true if stream with `stream_id` is ready. + bool IsStreamReady(StreamIdType stream_id) const { auto it = stream_infos_.find(stream_id); if (it == stream_infos_.end()) { QUICHE_DLOG(INFO) << "Stream " << stream_id << " not registered";
diff --git a/quiche/http2/core/write_scheduler.h b/quiche/http2/core/write_scheduler.h deleted file mode 100644 index ce0ddc1..0000000 --- a/quiche/http2/core/write_scheduler.h +++ /dev/null
@@ -1,153 +0,0 @@ -// Copyright (c) 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef QUICHE_HTTP2_CORE_WRITE_SCHEDULER_H_ -#define QUICHE_HTTP2_CORE_WRITE_SCHEDULER_H_ - -#include <cstdint> -#include <string> -#include <tuple> -#include <vector> - -#include "quiche/common/platform/api/quiche_export.h" -#include "quiche/spdy/core/spdy_protocol.h" - -namespace http2 { - -// Abstract superclass for classes that decide which SPDY or HTTP/2 stream to -// write next. Concrete subclasses implement various scheduling policies: -// -// PriorityWriteScheduler: implements SPDY priority-based stream scheduling, -// where (writable) higher-priority streams are always given precedence -// over lower-priority streams. -// -// The type used to represent stream IDs (StreamIdType) is templated in order -// to allow for use by both SPDY and QUIC codebases. It must be a POD that -// supports comparison (i.e., a numeric type). -// -// Each stream can be in one of two states: ready or not ready (for writing). -// Ready state is changed by calling the MarkStreamReady() and -// MarkStreamNotReady() methods. Only streams in the ready state can be -// returned by PopNextReadyStream(); when returned by that method, the stream's -// state changes to not ready. -template <typename StreamIdType> -class QUICHE_EXPORT WriteScheduler { - public: - typedef spdy::StreamPrecedence<StreamIdType> StreamPrecedenceType; - - virtual ~WriteScheduler() {} - - // Registers new stream |stream_id| with the scheduler, assigning it the - // given precedence. If the scheduler supports stream dependencies, the - // stream is inserted into the dependency tree under - // |precedence.parent_id()|. - // - // Preconditions: |stream_id| should be unregistered, and - // |precedence.parent_id()| should be registered or |kHttp2RootStreamId|. - virtual void RegisterStream(StreamIdType stream_id, - const StreamPrecedenceType& precedence) = 0; - - // Unregisters the given stream from the scheduler, which will no longer keep - // state for it. - // - // Preconditions: |stream_id| should be registered. - virtual void UnregisterStream(StreamIdType stream_id) = 0; - - // Returns true if the given stream is currently registered. - virtual bool StreamRegistered(StreamIdType stream_id) const = 0; - - // Returns the precedence of the specified stream. If the scheduler supports - // stream dependencies, calling |parent_id()| on the return value returns the - // stream's parent, and calling |exclusive()| returns true iff the specified - // stream is an only child of the parent stream. - // - // Preconditions: |stream_id| should be registered. - virtual StreamPrecedenceType GetStreamPrecedence( - StreamIdType stream_id) const = 0; - - // Updates the precedence of the given stream. If the scheduler supports - // stream dependencies, |stream_id|'s parent will be updated to be - // |precedence.parent_id()| if it is not already. - // - // Preconditions: |stream_id| should be unregistered, and - // |precedence.parent_id()| should be registered or |kHttp2RootStreamId|. - virtual void UpdateStreamPrecedence( - StreamIdType stream_id, const StreamPrecedenceType& precedence) = 0; - - // Returns child streams of the given stream, if any. If the scheduler - // doesn't support stream dependencies, returns an empty vector. - // - // Preconditions: |stream_id| should be registered. - virtual std::vector<StreamIdType> GetStreamChildren( - StreamIdType stream_id) const = 0; - - // Records time (in microseconds) of a read/write event for the given - // stream. - // - // Preconditions: |stream_id| should be registered. - virtual void RecordStreamEventTime(StreamIdType stream_id, - int64_t now_in_usec) = 0; - - // Returns time (in microseconds) of the last read/write event for a stream - // with higher priority than the priority of the given stream, or 0 if there - // is no such event. - // - // Preconditions: |stream_id| should be registered. - virtual int64_t GetLatestEventWithPrecedence( - StreamIdType stream_id) const = 0; - - // If the scheduler has any ready streams, returns the next scheduled - // ready stream, in the process transitioning the stream from ready to not - // ready. - // - // Preconditions: |HasReadyStreams() == true| - virtual StreamIdType PopNextReadyStream() = 0; - - // If the scheduler has any ready streams, returns the next scheduled - // ready stream and its priority, in the process transitioning the stream from - // ready to not ready. - // - // Preconditions: |HasReadyStreams() == true| - virtual std::tuple<StreamIdType, StreamPrecedenceType> - PopNextReadyStreamAndPrecedence() = 0; - - // Returns true if there's another stream ahead of the given stream in the - // scheduling queue. This function can be called to see if the given stream - // should yield work to another stream. - // - // Preconditions: |stream_id| should be registered. - virtual bool ShouldYield(StreamIdType stream_id) const = 0; - - // Marks the stream as ready to write. If the stream was already ready, does - // nothing. If add_to_front is true, the stream is scheduled ahead of other - // streams of the same priority/weight, otherwise it is scheduled behind them. - // - // Preconditions: |stream_id| should be registered. - virtual void MarkStreamReady(StreamIdType stream_id, bool add_to_front) = 0; - - // Marks the stream as not ready to write. If the stream is not registered or - // not ready, does nothing. - // - // Preconditions: |stream_id| should be registered. - virtual void MarkStreamNotReady(StreamIdType stream_id) = 0; - - // Returns true iff the scheduler has any ready streams. - virtual bool HasReadyStreams() const = 0; - - // Returns the number of streams currently marked ready. - virtual size_t NumReadyStreams() const = 0; - - // Returns true if stream with |stream_id| is ready. - virtual bool IsStreamReady(StreamIdType stream_id) const = 0; - - // Returns the number of registered streams. - virtual size_t NumRegisteredStreams() const = 0; - - // Returns summary of internal state, for logging/debugging. - virtual std::string DebugString() const = 0; -}; - -} // namespace http2 - -#endif // QUICHE_HTTP2_CORE_WRITE_SCHEDULER_H_