OLD | NEW |
| (Empty) |
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 #include <utility> | |
9 #include <vector> | |
10 | |
11 #include "base/logging.h" | |
12 #include "net/spdy/platform/api/spdy_estimate_memory_usage.h" | |
13 #include "net/spdy/spdy_buffer.h" | |
14 #include "net/spdy/spdy_buffer_producer.h" | |
15 #include "net/spdy/spdy_stream.h" | |
16 | |
17 namespace net { | |
18 | |
19 SpdyWriteQueue::PendingWrite::PendingWrite() {} | |
20 | |
21 SpdyWriteQueue::PendingWrite::PendingWrite( | |
22 SpdyFrameType frame_type, | |
23 std::unique_ptr<SpdyBufferProducer> frame_producer, | |
24 const base::WeakPtr<SpdyStream>& stream) | |
25 : frame_type(frame_type), | |
26 frame_producer(std::move(frame_producer)), | |
27 stream(stream), | |
28 has_stream(stream.get() != nullptr) {} | |
29 | |
30 SpdyWriteQueue::PendingWrite::~PendingWrite() {} | |
31 | |
32 SpdyWriteQueue::PendingWrite::PendingWrite(PendingWrite&& other) = default; | |
33 SpdyWriteQueue::PendingWrite& SpdyWriteQueue::PendingWrite::operator=( | |
34 PendingWrite&& other) = default; | |
35 | |
36 size_t SpdyWriteQueue::PendingWrite::EstimateMemoryUsage() const { | |
37 return SpdyEstimateMemoryUsage(frame_producer); | |
38 } | |
39 | |
40 SpdyWriteQueue::SpdyWriteQueue() : removing_writes_(false) {} | |
41 | |
42 SpdyWriteQueue::~SpdyWriteQueue() { | |
43 Clear(); | |
44 } | |
45 | |
46 bool SpdyWriteQueue::IsEmpty() const { | |
47 for (int i = MINIMUM_PRIORITY; i <= MAXIMUM_PRIORITY; i++) { | |
48 if (!queue_[i].empty()) | |
49 return false; | |
50 } | |
51 return true; | |
52 } | |
53 | |
54 void SpdyWriteQueue::Enqueue(RequestPriority priority, | |
55 SpdyFrameType frame_type, | |
56 std::unique_ptr<SpdyBufferProducer> frame_producer, | |
57 const base::WeakPtr<SpdyStream>& stream) { | |
58 CHECK(!removing_writes_); | |
59 CHECK_GE(priority, MINIMUM_PRIORITY); | |
60 CHECK_LE(priority, MAXIMUM_PRIORITY); | |
61 if (stream.get()) | |
62 DCHECK_EQ(stream->priority(), priority); | |
63 queue_[priority].push_back({frame_type, std::move(frame_producer), stream}); | |
64 } | |
65 | |
66 bool SpdyWriteQueue::Dequeue( | |
67 SpdyFrameType* frame_type, | |
68 std::unique_ptr<SpdyBufferProducer>* frame_producer, | |
69 base::WeakPtr<SpdyStream>* stream) { | |
70 CHECK(!removing_writes_); | |
71 for (int i = MAXIMUM_PRIORITY; i >= MINIMUM_PRIORITY; --i) { | |
72 if (!queue_[i].empty()) { | |
73 PendingWrite pending_write = std::move(queue_[i].front()); | |
74 queue_[i].pop_front(); | |
75 *frame_type = pending_write.frame_type; | |
76 *frame_producer = std::move(pending_write.frame_producer); | |
77 *stream = pending_write.stream; | |
78 if (pending_write.has_stream) | |
79 DCHECK(stream->get()); | |
80 return true; | |
81 } | |
82 } | |
83 return false; | |
84 } | |
85 | |
86 void SpdyWriteQueue::RemovePendingWritesForStream( | |
87 const base::WeakPtr<SpdyStream>& stream) { | |
88 CHECK(!removing_writes_); | |
89 removing_writes_ = true; | |
90 RequestPriority priority = stream->priority(); | |
91 CHECK_GE(priority, MINIMUM_PRIORITY); | |
92 CHECK_LE(priority, MAXIMUM_PRIORITY); | |
93 | |
94 DCHECK(stream.get()); | |
95 #if DCHECK_IS_ON() | |
96 // |stream| should not have pending writes in a queue not matching | |
97 // its priority. | |
98 for (int i = MINIMUM_PRIORITY; i <= MAXIMUM_PRIORITY; ++i) { | |
99 if (priority == i) | |
100 continue; | |
101 for (auto it = queue_[i].begin(); it != queue_[i].end(); ++it) | |
102 DCHECK_NE(it->stream.get(), stream.get()); | |
103 } | |
104 #endif | |
105 | |
106 // Defer deletion until queue iteration is complete, as | |
107 // SpdyBuffer::~SpdyBuffer() can result in callbacks into SpdyWriteQueue. | |
108 std::vector<std::unique_ptr<SpdyBufferProducer>> erased_buffer_producers; | |
109 | |
110 // Do the actual deletion and removal, preserving FIFO-ness. | |
111 std::deque<PendingWrite>& queue = queue_[priority]; | |
112 auto out_it = queue.begin(); | |
113 for (auto it = queue.begin(); it != queue.end(); ++it) { | |
114 if (it->stream.get() == stream.get()) { | |
115 erased_buffer_producers.push_back(std::move(it->frame_producer)); | |
116 } else { | |
117 *out_it = std::move(*it); | |
118 ++out_it; | |
119 } | |
120 } | |
121 queue.erase(out_it, queue.end()); | |
122 removing_writes_ = false; | |
123 } | |
124 | |
125 void SpdyWriteQueue::RemovePendingWritesForStreamsAfter( | |
126 SpdyStreamId last_good_stream_id) { | |
127 CHECK(!removing_writes_); | |
128 removing_writes_ = true; | |
129 std::vector<std::unique_ptr<SpdyBufferProducer>> erased_buffer_producers; | |
130 | |
131 for (int i = MINIMUM_PRIORITY; i <= MAXIMUM_PRIORITY; ++i) { | |
132 // Do the actual deletion and removal, preserving FIFO-ness. | |
133 std::deque<PendingWrite>& queue = queue_[i]; | |
134 auto out_it = queue.begin(); | |
135 for (auto it = queue.begin(); it != queue.end(); ++it) { | |
136 if (it->stream.get() && (it->stream->stream_id() > last_good_stream_id || | |
137 it->stream->stream_id() == 0)) { | |
138 erased_buffer_producers.push_back(std::move(it->frame_producer)); | |
139 } else { | |
140 *out_it = std::move(*it); | |
141 ++out_it; | |
142 } | |
143 } | |
144 queue.erase(out_it, queue.end()); | |
145 } | |
146 removing_writes_ = false; | |
147 } | |
148 | |
149 void SpdyWriteQueue::Clear() { | |
150 CHECK(!removing_writes_); | |
151 removing_writes_ = true; | |
152 std::vector<std::unique_ptr<SpdyBufferProducer>> erased_buffer_producers; | |
153 | |
154 for (int i = MINIMUM_PRIORITY; i <= MAXIMUM_PRIORITY; ++i) { | |
155 for (auto it = queue_[i].begin(); it != queue_[i].end(); ++it) { | |
156 erased_buffer_producers.push_back(std::move(it->frame_producer)); | |
157 } | |
158 queue_[i].clear(); | |
159 } | |
160 removing_writes_ = false; | |
161 } | |
162 | |
163 size_t SpdyWriteQueue::EstimateMemoryUsage() const { | |
164 return SpdyEstimateMemoryUsage(queue_); | |
165 } | |
166 | |
167 } // namespace net | |
OLD | NEW |