|  | // Copyright 2014 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 NET_QUIC_QUIC_WRITE_BLOCKED_LIST_H_ | 
|  | #define NET_QUIC_QUIC_WRITE_BLOCKED_LIST_H_ | 
|  |  | 
|  | #include <set> | 
|  |  | 
|  | #include "net/base/net_export.h" | 
|  | #include "net/quic/quic_protocol.h" | 
|  | #include "net/spdy/write_blocked_list.h" | 
|  |  | 
|  | namespace net { | 
|  |  | 
|  | // Keeps tracks of the QUIC streams that have data to write, sorted by | 
|  | // priority.  QUIC stream priority order is: | 
|  | // Crypto stream > Headers stream > Data streams by requested priority. | 
|  | class NET_EXPORT_PRIVATE QuicWriteBlockedList { | 
|  | private: | 
|  | typedef WriteBlockedList<QuicStreamId> QuicWriteBlockedListBase; | 
|  |  | 
|  | public: | 
|  | static const QuicPriority kHighestPriority; | 
|  | static const QuicPriority kLowestPriority; | 
|  |  | 
|  | QuicWriteBlockedList(); | 
|  | ~QuicWriteBlockedList(); | 
|  |  | 
|  | bool HasWriteBlockedDataStreams() const { | 
|  | return base_write_blocked_list_.HasWriteBlockedStreams(); | 
|  | } | 
|  |  | 
|  | bool HasWriteBlockedCryptoOrHeadersStream() const { | 
|  | return crypto_stream_blocked_ || headers_stream_blocked_; | 
|  | } | 
|  |  | 
|  | size_t NumBlockedStreams() const { | 
|  | size_t num_blocked = base_write_blocked_list_.NumBlockedStreams(); | 
|  | if (crypto_stream_blocked_) { | 
|  | ++num_blocked; | 
|  | } | 
|  | if (headers_stream_blocked_) { | 
|  | ++num_blocked; | 
|  | } | 
|  |  | 
|  | return num_blocked; | 
|  | } | 
|  |  | 
|  | QuicStreamId PopFront() { | 
|  | if (crypto_stream_blocked_) { | 
|  | crypto_stream_blocked_ = false; | 
|  | return kCryptoStreamId; | 
|  | } | 
|  |  | 
|  | if (headers_stream_blocked_) { | 
|  | headers_stream_blocked_ = false; | 
|  | return kHeadersStreamId; | 
|  | } | 
|  |  | 
|  | SpdyPriority priority = | 
|  | base_write_blocked_list_.GetHighestPriorityWriteBlockedList(); | 
|  | QuicStreamId id = base_write_blocked_list_.PopFront(priority); | 
|  | blocked_streams_.erase(id); | 
|  | return id; | 
|  | } | 
|  |  | 
|  | void PushBack(QuicStreamId stream_id, QuicPriority priority) { | 
|  | if (stream_id == kCryptoStreamId) { | 
|  | DCHECK_EQ(kHighestPriority, priority); | 
|  | // TODO(avd) Add DCHECK(!crypto_stream_blocked_) | 
|  | crypto_stream_blocked_ = true; | 
|  | return; | 
|  | } | 
|  |  | 
|  | if (stream_id == kHeadersStreamId) { | 
|  | DCHECK_EQ(kHighestPriority, priority); | 
|  | // TODO(avd) Add DCHECK(!headers_stream_blocked_); | 
|  | headers_stream_blocked_ = true; | 
|  | return; | 
|  | } | 
|  |  | 
|  | if (blocked_streams_.find(stream_id) != blocked_streams_.end()) { | 
|  | DVLOG(1) << "Stream " << stream_id << " already in write blocked list."; | 
|  | return; | 
|  | } | 
|  |  | 
|  | base_write_blocked_list_.PushBack( | 
|  | stream_id, static_cast<SpdyPriority>(priority)); | 
|  | blocked_streams_.insert(stream_id); | 
|  | return; | 
|  | } | 
|  |  | 
|  | bool crypto_stream_blocked() const { return crypto_stream_blocked_; } | 
|  | bool headers_stream_blocked() const { return headers_stream_blocked_; } | 
|  |  | 
|  | private: | 
|  | QuicWriteBlockedListBase base_write_blocked_list_; | 
|  | bool crypto_stream_blocked_; | 
|  | bool headers_stream_blocked_; | 
|  |  | 
|  | // Keep track of write blocked streams in a set for faster membership checking | 
|  | // than iterating over the base_write_blocked_list_. The contents of this set | 
|  | // should mirror the contents of base_write_blocked_list_. | 
|  | std::set<QuicStreamId> blocked_streams_; | 
|  |  | 
|  | DISALLOW_COPY_AND_ASSIGN(QuicWriteBlockedList); | 
|  | }; | 
|  |  | 
|  | }  // namespace net | 
|  |  | 
|  |  | 
|  | #endif  // NET_QUIC_QUIC_WRITE_BLOCKED_LIST_H_ |