1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "net/spdy/spdy_write_queue.h" 6 7 #include <cstddef> 8 9 #include "base/logging.h" 10 #include "net/spdy/spdy_buffer.h" 11 #include "net/spdy/spdy_buffer_producer.h" 12 #include "net/spdy/spdy_stream.h" 13 14 namespace net { 15 16 SpdyWriteQueue::PendingWrite::PendingWrite() : frame_producer(NULL) {} 17 18 SpdyWriteQueue::PendingWrite::PendingWrite( 19 SpdyFrameType frame_type, 20 SpdyBufferProducer* frame_producer, 21 const base::WeakPtr<SpdyStream>& stream) 22 : frame_type(frame_type), 23 frame_producer(frame_producer), 24 stream(stream), 25 has_stream(stream.get() != NULL) {} 26 27 SpdyWriteQueue::PendingWrite::~PendingWrite() {} 28 29 SpdyWriteQueue::SpdyWriteQueue() {} 30 31 SpdyWriteQueue::~SpdyWriteQueue() { 32 Clear(); 33 } 34 35 bool SpdyWriteQueue::IsEmpty() const { 36 for (int i = MINIMUM_PRIORITY; i <= MAXIMUM_PRIORITY; i++) { 37 if (!queue_[i].empty()) 38 return false; 39 } 40 return true; 41 } 42 43 void SpdyWriteQueue::Enqueue(RequestPriority priority, 44 SpdyFrameType frame_type, 45 scoped_ptr<SpdyBufferProducer> frame_producer, 46 const base::WeakPtr<SpdyStream>& stream) { 47 CHECK_GE(priority, MINIMUM_PRIORITY); 48 CHECK_LE(priority, MAXIMUM_PRIORITY); 49 if (stream.get()) 50 DCHECK_EQ(stream->priority(), priority); 51 queue_[priority].push_back( 52 PendingWrite(frame_type, frame_producer.release(), stream)); 53 } 54 55 bool SpdyWriteQueue::Dequeue(SpdyFrameType* frame_type, 56 scoped_ptr<SpdyBufferProducer>* frame_producer, 57 base::WeakPtr<SpdyStream>* stream) { 58 for (int i = MAXIMUM_PRIORITY; i >= MINIMUM_PRIORITY; --i) { 59 if (!queue_[i].empty()) { 60 PendingWrite pending_write = queue_[i].front(); 61 queue_[i].pop_front(); 62 *frame_type = pending_write.frame_type; 63 frame_producer->reset(pending_write.frame_producer); 64 *stream = pending_write.stream; 65 if (pending_write.has_stream) 66 DCHECK(stream->get()); 67 return true; 68 } 69 } 70 return false; 71 } 72 73 void SpdyWriteQueue::RemovePendingWritesForStream( 74 const base::WeakPtr<SpdyStream>& stream) { 75 RequestPriority priority = stream->priority(); 76 CHECK_GE(priority, MINIMUM_PRIORITY); 77 CHECK_LE(priority, MAXIMUM_PRIORITY); 78 79 DCHECK(stream.get()); 80 if (DCHECK_IS_ON()) { 81 // |stream| should not have pending writes in a queue not matching 82 // its priority. 83 for (int i = MINIMUM_PRIORITY; i <= MAXIMUM_PRIORITY; ++i) { 84 if (priority == i) 85 continue; 86 for (std::deque<PendingWrite>::const_iterator it = queue_[i].begin(); 87 it != queue_[i].end(); ++it) { 88 DCHECK_NE(it->stream.get(), stream.get()); 89 } 90 } 91 } 92 93 // Do the actual deletion and removal, preserving FIFO-ness. 94 std::deque<PendingWrite>* queue = &queue_[priority]; 95 std::deque<PendingWrite>::iterator out_it = queue->begin(); 96 for (std::deque<PendingWrite>::const_iterator it = queue->begin(); 97 it != queue->end(); ++it) { 98 if (it->stream.get() == stream.get()) { 99 delete it->frame_producer; 100 } else { 101 *out_it = *it; 102 ++out_it; 103 } 104 } 105 queue->erase(out_it, queue->end()); 106 } 107 108 void SpdyWriteQueue::RemovePendingWritesForStreamsAfter( 109 SpdyStreamId last_good_stream_id) { 110 for (int i = MINIMUM_PRIORITY; i <= MAXIMUM_PRIORITY; ++i) { 111 // Do the actual deletion and removal, preserving FIFO-ness. 112 std::deque<PendingWrite>* queue = &queue_[i]; 113 std::deque<PendingWrite>::iterator out_it = queue->begin(); 114 for (std::deque<PendingWrite>::const_iterator it = queue->begin(); 115 it != queue->end(); ++it) { 116 if (it->stream.get() && (it->stream->stream_id() > last_good_stream_id || 117 it->stream->stream_id() == 0)) { 118 delete it->frame_producer; 119 } else { 120 *out_it = *it; 121 ++out_it; 122 } 123 } 124 queue->erase(out_it, queue->end()); 125 } 126 } 127 128 void SpdyWriteQueue::Clear() { 129 for (int i = MINIMUM_PRIORITY; i <= MAXIMUM_PRIORITY; ++i) { 130 for (std::deque<PendingWrite>::iterator it = queue_[i].begin(); 131 it != queue_[i].end(); ++it) { 132 delete it->frame_producer; 133 } 134 queue_[i].clear(); 135 } 136 } 137 138 } // namespace net 139