Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1117)

Side by Side Diff: net/http/http_pipelined_host_impl.cc

Issue 8820005: Fix race between OnPipelineFeedback and (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 9 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "net/http/http_pipelined_host_impl.h" 5 #include "net/http/http_pipelined_host_impl.h"
6 6
7 #include "base/stl_util.h" 7 #include "base/stl_util.h"
8 #include "net/http/http_pipelined_connection_impl.h" 8 #include "net/http/http_pipelined_connection_impl.h"
9 #include "net/http/http_pipelined_stream.h" 9 #include "net/http/http_pipelined_stream.h"
10 10
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
62 was_npn_negotiated); 62 was_npn_negotiated);
63 PipelineInfo info; 63 PipelineInfo info;
64 pipelines_.insert(std::make_pair(pipeline, info)); 64 pipelines_.insert(std::make_pair(pipeline, info));
65 return pipeline->CreateNewStream(); 65 return pipeline->CreateNewStream();
66 } 66 }
67 67
68 HttpPipelinedStream* HttpPipelinedHostImpl::CreateStreamOnExistingPipeline() { 68 HttpPipelinedStream* HttpPipelinedHostImpl::CreateStreamOnExistingPipeline() {
69 HttpPipelinedConnection* available_pipeline = NULL; 69 HttpPipelinedConnection* available_pipeline = NULL;
70 for (PipelineInfoMap::iterator it = pipelines_.begin(); 70 for (PipelineInfoMap::iterator it = pipelines_.begin();
71 it != pipelines_.end(); ++it) { 71 it != pipelines_.end(); ++it) {
72 if (it->first->usable() && 72 if (CanPipelineAcceptRequests(it->first) &&
73 it->first->active() &&
74 it->first->depth() < GetPipelineCapacity() &&
75 (!available_pipeline || 73 (!available_pipeline ||
76 it->first->depth() < available_pipeline->depth())) { 74 it->first->depth() < available_pipeline->depth())) {
77 available_pipeline = it->first; 75 available_pipeline = it->first;
78 } 76 }
79 } 77 }
80 if (!available_pipeline) { 78 if (!available_pipeline) {
81 return NULL; 79 return NULL;
82 } 80 }
83 return available_pipeline->CreateNewStream(); 81 return available_pipeline->CreateNewStream();
84 } 82 }
85 83
86 bool HttpPipelinedHostImpl::IsExistingPipelineAvailable() const { 84 bool HttpPipelinedHostImpl::IsExistingPipelineAvailable() const {
87 for (PipelineInfoMap::const_iterator it = pipelines_.begin(); 85 for (PipelineInfoMap::const_iterator it = pipelines_.begin();
88 it != pipelines_.end(); ++it) { 86 it != pipelines_.end(); ++it) {
89 if (it->first->usable() && 87 if (CanPipelineAcceptRequests(it->first)) {
90 it->first->active() &&
91 it->first->depth() < GetPipelineCapacity()) {
92 return true; 88 return true;
93 } 89 }
94 } 90 }
95 return false; 91 return false;
96 } 92 }
97 93
98 const HostPortPair& HttpPipelinedHostImpl::origin() const { 94 const HostPortPair& HttpPipelinedHostImpl::origin() const {
99 return origin_; 95 return origin_;
100 } 96 }
101 97
102 void HttpPipelinedHostImpl::OnPipelineEmpty(HttpPipelinedConnection* pipeline) { 98 void HttpPipelinedHostImpl::OnPipelineEmpty(HttpPipelinedConnection* pipeline) {
103 CHECK(ContainsKey(pipelines_, pipeline)); 99 CHECK(ContainsKey(pipelines_, pipeline));
104 pipelines_.erase(pipeline); 100 pipelines_.erase(pipeline);
105 delete pipeline; 101 delete pipeline;
106 if (pipelines_.empty()) { 102 if (pipelines_.empty()) {
107 delegate_->OnHostIdle(this); 103 delegate_->OnHostIdle(this);
108 // WARNING: We'll probably be deleted here. 104 // WARNING: We'll probably be deleted here.
109 } 105 }
110 } 106 }
111 107
112 void HttpPipelinedHostImpl::OnPipelineHasCapacity( 108 void HttpPipelinedHostImpl::OnPipelineHasCapacity(
113 HttpPipelinedConnection* pipeline) { 109 HttpPipelinedConnection* pipeline) {
114 CHECK(ContainsKey(pipelines_, pipeline)); 110 CHECK(ContainsKey(pipelines_, pipeline));
115 if (pipeline->usable() && 111 if (CanPipelineAcceptRequests(pipeline)) {
116 capability_ != INCAPABLE &&
117 pipeline->depth() < GetPipelineCapacity()) {
118 delegate_->OnHostHasAdditionalCapacity(this); 112 delegate_->OnHostHasAdditionalCapacity(this);
119 } 113 }
120 if (!pipeline->depth()) { 114 if (!pipeline->depth()) {
121 OnPipelineEmpty(pipeline); 115 OnPipelineEmpty(pipeline);
122 // WARNING: We might be deleted here. 116 // WARNING: We might be deleted here.
123 } 117 }
124 } 118 }
125 119
126 void HttpPipelinedHostImpl::OnPipelineFeedback( 120 void HttpPipelinedHostImpl::OnPipelineFeedback(
127 HttpPipelinedConnection* pipeline, 121 HttpPipelinedConnection* pipeline,
128 HttpPipelinedConnection::Feedback feedback) { 122 HttpPipelinedConnection::Feedback feedback) {
129 CHECK(ContainsKey(pipelines_, pipeline)); 123 CHECK(ContainsKey(pipelines_, pipeline));
130 switch (feedback) { 124 switch (feedback) {
131 case HttpPipelinedConnection::OK: 125 case HttpPipelinedConnection::OK:
132 ++pipelines_[pipeline].num_successes; 126 ++pipelines_[pipeline].num_successes;
133 if (capability_ == UNKNOWN) { 127 if (capability_ == UNKNOWN) {
134 capability_ = PROBABLY_CAPABLE; 128 capability_ = PROBABLY_CAPABLE;
135 for (PipelineInfoMap::iterator it = pipelines_.begin(); 129 NotifyAllPipelinesHaveCapacity();
136 it != pipelines_.end(); ++it) {
137 OnPipelineHasCapacity(it->first);
138 }
139 } else if (capability_ == PROBABLY_CAPABLE && 130 } else if (capability_ == PROBABLY_CAPABLE &&
140 pipelines_[pipeline].num_successes >= 131 pipelines_[pipeline].num_successes >=
141 kNumKnownSuccessesThreshold) { 132 kNumKnownSuccessesThreshold) {
142 capability_ = CAPABLE; 133 capability_ = CAPABLE;
143 delegate_->OnHostDeterminedCapability(this, CAPABLE); 134 delegate_->OnHostDeterminedCapability(this, CAPABLE);
144 } 135 }
145 break; 136 break;
146 137
147 case HttpPipelinedConnection::PIPELINE_SOCKET_ERROR: 138 case HttpPipelinedConnection::PIPELINE_SOCKET_ERROR:
148 case HttpPipelinedConnection::OLD_HTTP_VERSION: 139 case HttpPipelinedConnection::OLD_HTTP_VERSION:
(...skipping 20 matching lines...) Expand all
169 case UNKNOWN: 160 case UNKNOWN:
170 capacity = 1; 161 capacity = 1;
171 break; 162 break;
172 163
173 default: 164 default:
174 CHECK(false) << "Unkown pipeline capability: " << capability_; 165 CHECK(false) << "Unkown pipeline capability: " << capability_;
175 } 166 }
176 return capacity; 167 return capacity;
177 } 168 }
178 169
170 bool HttpPipelinedHostImpl::CanPipelineAcceptRequests(
171 HttpPipelinedConnection* pipeline) const {
172 return pipeline->usable() &&
173 pipeline->active() &&
174 capability_ != INCAPABLE &&
mmenke 2011/12/06 15:29:03 nit: Seems a little odd to have this in the middl
James Simonsen 2011/12/06 19:41:35 Done.
175 pipeline->depth() < GetPipelineCapacity();
176 }
177
178 void HttpPipelinedHostImpl::NotifyAllPipelinesHaveCapacity() {
179 // Calling OnPipelineHasCapacity() can have side effects that include
180 // deleting and removing entries from |pipelines_|.
181 PipelineInfoMap pipelines_to_notify = pipelines_;
182 for (PipelineInfoMap::iterator it = pipelines_to_notify.begin();
183 it != pipelines_to_notify.end(); ++it) {
184 if (pipelines_.find(it->first) != pipelines_.end()) {
185 OnPipelineHasCapacity(it->first);
186 }
187 }
188 }
189
179 HttpPipelinedHostImpl::PipelineInfo::PipelineInfo() 190 HttpPipelinedHostImpl::PipelineInfo::PipelineInfo()
180 : num_successes(0) { 191 : num_successes(0) {
181 } 192 }
182 193
183 } // namespace net 194 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698