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 = 0; i < NUM_PRIORITIES; 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 if (stream.get()) 48 DCHECK_EQ(stream->priority(), priority); 49 queue_[priority].push_back( 50 PendingWrite(frame_type, frame_producer.release(), stream)); 51 } 52 53 bool SpdyWriteQueue::Dequeue(SpdyFrameType* frame_type, 54 scoped_ptr<SpdyBufferProducer>* frame_producer, 55 base::WeakPtr<SpdyStream>* stream) { 56 for (int i = NUM_PRIORITIES - 1; i >= 0; --i) { 57 if (!queue_[i].empty()) { 58 PendingWrite pending_write = queue_[i].front(); 59 queue_[i].pop_front(); 60 *frame_type = pending_write.frame_type; 61 frame_producer->reset(pending_write.frame_producer); 62 *stream = pending_write.stream; 63 if (pending_write.has_stream) 64 DCHECK(stream->get()); 65 return true; 66 } 67 } 68 return false; 69 } 70 71 void SpdyWriteQueue::RemovePendingWritesForStream( 72 const base::WeakPtr<SpdyStream>& stream) { 73 DCHECK(stream.get()); 74 if (DCHECK_IS_ON()) { 75 // |stream| should not have pending writes in a queue not matching 76 // its priority. 77 for (int i = 0; i < NUM_PRIORITIES; ++i) { 78 if (stream->priority() == i) 79 continue; 80 for (std::deque<PendingWrite>::const_iterator it = queue_[i].begin(); 81 it != queue_[i].end(); ++it) { 82 DCHECK_NE(it->stream.get(), stream.get()); 83 } 84 } 85 } 86 87 // Do the actual deletion and removal, preserving FIFO-ness. 88 std::deque<PendingWrite>* queue = &queue_[stream->priority()]; 89 std::deque<PendingWrite>::iterator out_it = queue->begin(); 90 for (std::deque<PendingWrite>::const_iterator it = queue->begin(); 91 it != queue->end(); ++it) { 92 if (it->stream.get() == stream.get()) { 93 delete it->frame_producer; 94 } else { 95 *out_it = *it; 96 ++out_it; 97 } 98 } 99 queue->erase(out_it, queue->end()); 100 } 101 102 void SpdyWriteQueue::RemovePendingWritesForStreamsAfter( 103 SpdyStreamId last_good_stream_id) { 104 for (int i = 0; i < NUM_PRIORITIES; ++i) { 105 // Do the actual deletion and removal, preserving FIFO-ness. 106 std::deque<PendingWrite>* queue = &queue_[i]; 107 std::deque<PendingWrite>::iterator out_it = queue->begin(); 108 for (std::deque<PendingWrite>::const_iterator it = queue->begin(); 109 it != queue->end(); ++it) { 110 if (it->stream.get() && (it->stream->stream_id() > last_good_stream_id || 111 it->stream->stream_id() == 0)) { 112 delete it->frame_producer; 113 } else { 114 *out_it = *it; 115 ++out_it; 116 } 117 } 118 queue->erase(out_it, queue->end()); 119 } 120 } 121 122 void SpdyWriteQueue::Clear() { 123 for (int i = 0; i < NUM_PRIORITIES; ++i) { 124 for (std::deque<PendingWrite>::iterator it = queue_[i].begin(); 125 it != queue_[i].end(); ++it) { 126 delete it->frame_producer; 127 } 128 queue_[i].clear(); 129 } 130 } 131 132 } // namespace net 133