Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 "content/browser/loader/resource_scheduler.h" | 5 #include "content/browser/loader/resource_scheduler.h" |
| 6 | 6 |
| 7 #include <stdint.h> | 7 #include <stdint.h> |
| 8 #include <set> | 8 #include <set> |
| 9 #include <string> | 9 #include <string> |
| 10 #include <utility> | 10 #include <utility> |
| (...skipping 14 matching lines...) Expand all Loading... | |
| 25 #include "net/base/load_flags.h" | 25 #include "net/base/load_flags.h" |
| 26 #include "net/base/request_priority.h" | 26 #include "net/base/request_priority.h" |
| 27 #include "net/http/http_server_properties.h" | 27 #include "net/http/http_server_properties.h" |
| 28 #include "net/url_request/url_request.h" | 28 #include "net/url_request/url_request.h" |
| 29 #include "net/url_request/url_request_context.h" | 29 #include "net/url_request/url_request_context.h" |
| 30 | 30 |
| 31 namespace content { | 31 namespace content { |
| 32 | 32 |
| 33 namespace { | 33 namespace { |
| 34 | 34 |
| 35 enum StartMode { | 35 enum ResumeMode { |
| 36 START_SYNC, | 36 RESUME_SYNC, |
| 37 START_ASYNC | 37 RESUME_ASYNC |
| 38 }; | 38 }; |
| 39 | 39 |
| 40 // Field trial constants | 40 // Field trial constants |
| 41 const char kRequestLimitFieldTrial[] = "OutstandingRequestLimiting"; | 41 const char kRequestLimitFieldTrial[] = "OutstandingRequestLimiting"; |
| 42 const char kRequestLimitFieldTrialGroupPrefix[] = "Limit"; | 42 const char kRequestLimitFieldTrialGroupPrefix[] = "Limit"; |
| 43 | 43 |
| 44 const char kResourcePrioritiesFieldTrial[] = "ResourcePriorities"; | 44 const char kResourcePrioritiesFieldTrial[] = "ResourcePriorities"; |
| 45 | 45 |
| 46 // Flags identifying various attributes of the request that are used | 46 // Flags identifying various attributes of the request that are used |
| 47 // when making scheduling decisions. | 47 // when making scheduling decisions. |
| (...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 144 // interact with the request. | 144 // interact with the request. |
| 145 class ResourceScheduler::ScheduledResourceRequest : public ResourceThrottle { | 145 class ResourceScheduler::ScheduledResourceRequest : public ResourceThrottle { |
| 146 public: | 146 public: |
| 147 ScheduledResourceRequest(const ClientId& client_id, | 147 ScheduledResourceRequest(const ClientId& client_id, |
| 148 net::URLRequest* request, | 148 net::URLRequest* request, |
| 149 ResourceScheduler* scheduler, | 149 ResourceScheduler* scheduler, |
| 150 const RequestPriorityParams& priority, | 150 const RequestPriorityParams& priority, |
| 151 bool is_async) | 151 bool is_async) |
| 152 : client_id_(client_id), | 152 : client_id_(client_id), |
| 153 request_(request), | 153 request_(request), |
| 154 ready_(false), | 154 paused_(false), |
| 155 deferred_(false), | |
| 156 is_async_(is_async), | 155 is_async_(is_async), |
| 157 attributes_(kAttributeNone), | 156 attributes_(kAttributeNone), |
| 158 scheduler_(scheduler), | 157 scheduler_(scheduler), |
| 159 priority_(priority), | 158 priority_(priority), |
| 160 fifo_ordering_(0), | 159 fifo_ordering_(0), |
| 161 weak_ptr_factory_(this) { | 160 weak_ptr_factory_(this) { |
| 162 DCHECK(!request_->GetUserData(kUserDataKey)); | 161 DCHECK(!request_->GetUserData(kUserDataKey)); |
| 163 request_->SetUserData(kUserDataKey, new UnownedPointer(this)); | 162 request_->SetUserData(kUserDataKey, new UnownedPointer(this)); |
| 164 } | 163 } |
| 165 | 164 |
| 166 ~ScheduledResourceRequest() override { | 165 ~ScheduledResourceRequest() override { |
| 167 request_->RemoveUserData(kUserDataKey); | 166 request_->RemoveUserData(kUserDataKey); |
| 168 scheduler_->RemoveRequest(this); | 167 scheduler_->RemoveRequest(this); |
| 169 } | 168 } |
|
mmenke
2016/02/25 18:09:51
Fix indent (Or just run git cl format)
| |
| 170 | 169 |
| 171 static ScheduledResourceRequest* ForRequest(net::URLRequest* request) { | 170 static ScheduledResourceRequest* ForRequest(net::URLRequest* request) { |
| 172 return static_cast<UnownedPointer*>(request->GetUserData(kUserDataKey)) | 171 return static_cast<UnownedPointer*>(request->GetUserData(kUserDataKey)) |
| 173 ->get(); | 172 ->get(); |
| 174 } | 173 } |
| 175 | 174 |
| 176 // Starts the request. If |start_mode| is START_ASYNC, the request will not | 175 // Resumes the request. If |resume_mode| is RESUME_ASYNC, the request will not |
| 177 // be started immediately. | 176 // be resumed immediately. |
| 178 void Start(StartMode start_mode) { | 177 void Resume(ResumeMode resume_mode) { |
| 179 DCHECK(!ready_); | |
| 180 | |
| 181 // If the request was cancelled, do nothing. | 178 // If the request was cancelled, do nothing. |
| 182 if (!request_->status().is_success()) | 179 if (!request_->status().is_success()) |
| 183 return; | 180 return; |
| 184 | 181 |
| 185 // If the request was deferred, need to start it. Otherwise, will just not | 182 // If the request was paused, need to resume it. Otherwise, will just not |
| 186 // defer starting it in the first place, and the value of |start_mode| | 183 // pause it in the first place, and the value of |resume_mode| |
| 187 // makes no difference. | 184 // makes no difference. |
| 188 if (deferred_) { | 185 if (paused_) { |
| 189 // If can't start the request synchronously, post a task to start the | 186 // If can't start the request synchronously, post a task to start the |
| 190 // request. | 187 // request. |
| 191 if (start_mode == START_ASYNC) { | 188 if (resume_mode == RESUME_ASYNC) { |
| 192 base::ThreadTaskRunnerHandle::Get()->PostTask( | 189 base::ThreadTaskRunnerHandle::Get()->PostTask( |
| 193 FROM_HERE, | 190 FROM_HERE, |
| 194 base::Bind(&ScheduledResourceRequest::Start, | 191 base::Bind(&ScheduledResourceRequest::Resume, |
| 195 weak_ptr_factory_.GetWeakPtr(), | 192 weak_ptr_factory_.GetWeakPtr(), |
| 196 START_SYNC)); | 193 RESUME_SYNC)); |
| 197 return; | 194 return; |
| 198 } | 195 } |
| 199 deferred_ = false; | 196 paused_ = false; |
| 200 controller()->Resume(); | 197 controller()->Resume(); |
| 201 } | 198 } |
| 202 | |
| 203 ready_ = true; | |
| 204 } | 199 } |
| 205 | 200 |
| 206 void set_request_priority_params(const RequestPriorityParams& priority) { | 201 void set_request_priority_params(const RequestPriorityParams& priority) { |
| 207 priority_ = priority; | 202 priority_ = priority; |
| 208 } | 203 } |
| 209 const RequestPriorityParams& get_request_priority_params() const { | 204 const RequestPriorityParams& get_request_priority_params() const { |
| 210 return priority_; | 205 return priority_; |
| 211 } | 206 } |
| 212 const ClientId& client_id() const { return client_id_; } | 207 const ClientId& client_id() const { return client_id_; } |
| 213 net::URLRequest* url_request() { return request_; } | 208 net::URLRequest* url_request() { return request_; } |
| (...skipping 20 matching lines...) Expand all Loading... | |
| 234 | 229 |
| 235 private: | 230 private: |
| 236 ScheduledResourceRequest* const pointer_; | 231 ScheduledResourceRequest* const pointer_; |
| 237 | 232 |
| 238 DISALLOW_COPY_AND_ASSIGN(UnownedPointer); | 233 DISALLOW_COPY_AND_ASSIGN(UnownedPointer); |
| 239 }; | 234 }; |
| 240 | 235 |
| 241 static const void* const kUserDataKey; | 236 static const void* const kUserDataKey; |
| 242 | 237 |
| 243 // ResourceThrottle interface: | 238 // ResourceThrottle interface: |
| 244 void WillStartRequest(bool* defer) override { | 239 void WillStartUsingNetwork(bool* defer) override { |
| 245 deferred_ = *defer = !ready_; | 240 paused_ = *defer = !scheduler_->ShouldSendRequest(this); |
| 246 } | 241 } |
| 247 | 242 |
| 248 const char* GetNameForLogging() const override { return "ResourceScheduler"; } | 243 const char* GetNameForLogging() const override { return "ResourceScheduler"; } |
| 249 | 244 |
| 250 const ClientId client_id_; | 245 const ClientId client_id_; |
| 251 net::URLRequest* request_; | 246 net::URLRequest* request_; |
| 252 bool ready_; | 247 bool paused_; |
| 253 bool deferred_; | |
| 254 bool is_async_; | 248 bool is_async_; |
| 255 RequestAttributes attributes_; | 249 RequestAttributes attributes_; |
| 256 ResourceScheduler* scheduler_; | 250 ResourceScheduler* scheduler_; |
| 257 RequestPriorityParams priority_; | 251 RequestPriorityParams priority_; |
| 258 uint32_t fifo_ordering_; | 252 uint32_t fifo_ordering_; |
| 259 | 253 |
| 260 base::WeakPtrFactory<ResourceScheduler::ScheduledResourceRequest> | 254 base::WeakPtrFactory<ResourceScheduler::ScheduledResourceRequest> |
| 261 weak_ptr_factory_; | 255 weak_ptr_factory_; |
| 262 | 256 |
| 263 DISALLOW_COPY_AND_ASSIGN(ScheduledResourceRequest); | 257 DISALLOW_COPY_AND_ASSIGN(ScheduledResourceRequest); |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 295 explicit Client(ResourceScheduler* scheduler) | 289 explicit Client(ResourceScheduler* scheduler) |
| 296 : is_loaded_(false), | 290 : is_loaded_(false), |
| 297 has_html_body_(false), | 291 has_html_body_(false), |
| 298 using_spdy_proxy_(false), | 292 using_spdy_proxy_(false), |
| 299 scheduler_(scheduler), | 293 scheduler_(scheduler), |
| 300 in_flight_delayable_count_(0), | 294 in_flight_delayable_count_(0), |
| 301 total_layout_blocking_count_(0) {} | 295 total_layout_blocking_count_(0) {} |
| 302 | 296 |
| 303 ~Client() {} | 297 ~Client() {} |
| 304 | 298 |
| 305 void ScheduleRequest(net::URLRequest* url_request, | 299 void ScheduleRequest(net::URLRequest* url_request, |
|
mmenke
2016/02/25 18:09:51
SchedulerRequest -> AddRequest? This is no longer
| |
| 306 ScheduledResourceRequest* request) { | 300 ScheduledResourceRequest* request) { |
| 301 all_requests_.insert(request); | |
| 307 SetRequestAttributes(request, DetermineRequestAttributes(request)); | 302 SetRequestAttributes(request, DetermineRequestAttributes(request)); |
| 303 } | |
| 304 | |
| 305 bool ShouldSendRequest(ScheduledResourceRequest* request) { | |
|
mmenke
2016/02/25 18:09:51
Think this needs a description
mmenke
2016/02/25 18:09:51
This should be renamed. "Should" implies no side
| |
| 308 if (ShouldStartRequest(request) == START_REQUEST) { | 306 if (ShouldStartRequest(request) == START_REQUEST) { |
| 309 // New requests can be started synchronously without issue. | 307 InsertInFlightRequest(request); |
| 310 StartRequest(request, START_SYNC); | 308 return true; |
| 311 } else { | 309 } else { |
| 312 pending_requests_.Insert(request); | 310 pending_requests_.Insert(request); |
|
mmenke
2016/02/25 18:09:51
pending_requests_ -> paused_requests_, maybe?
| |
| 311 return false; | |
| 313 } | 312 } |
| 314 } | 313 } |
| 315 | 314 |
| 316 void RemoveRequest(ScheduledResourceRequest* request) { | 315 void RemoveRequest(ScheduledResourceRequest* request) { |
| 317 if (pending_requests_.IsQueued(request)) { | 316 if (pending_requests_.IsQueued(request)) |
| 318 pending_requests_.Erase(request); | 317 pending_requests_.Erase(request); |
|
mmenke
2016/02/25 18:09:51
Why did you remove the DCHECK here?
| |
| 319 DCHECK(!ContainsKey(in_flight_requests_, request)); | 318 else if (ContainsKey(in_flight_requests_, request)) |
| 320 } else { | |
| 321 EraseInFlightRequest(request); | 319 EraseInFlightRequest(request); |
|
mmenke
2016/02/25 18:09:51
nit: Network stack team generally uses braces for
| |
| 322 | 320 SetRequestAttributes(request, kAttributeNone); |
| 323 // Removing this request may have freed up another to load. | 321 all_requests_.erase(request); |
|
mmenke
2016/02/25 18:09:51
We should update the list before calling SetReques
| |
| 324 LoadAnyStartablePendingRequests(); | 322 // Removing this request may have freed up another to load or may have |
| 325 } | 323 // cleared out the queue of layout-blocking requests. |
| 324 LoadAnyStartablePendingRequests(); | |
| 326 } | 325 } |
| 327 | 326 |
| 328 RequestSet StartAndRemoveAllRequests() { | 327 RequestSet StartAndRemoveAllRequests() { |
| 329 // First start any pending requests so that they will be moved into | 328 // First start any pending requests so that they will be moved into |
| 330 // in_flight_requests_. This may exceed the limits | 329 // in_flight_requests_. This may exceed the limits |
| 331 // kDefaultMaxNumDelayableRequestsPerClient and | 330 // kDefaultMaxNumDelayableRequestsPerClient and |
| 332 // kMaxNumDelayableRequestsPerHost, so this method must not do anything that | 331 // kMaxNumDelayableRequestsPerHost, so this method must not do anything that |
| 333 // depends on those limits before calling ClearInFlightRequests() below. | 332 // depends on those limits before calling ClearInFlightRequests() below. |
| 334 while (!pending_requests_.IsEmpty()) { | 333 while (!pending_requests_.IsEmpty()) { |
| 335 ScheduledResourceRequest* request = | 334 ScheduledResourceRequest* request = |
| 336 *pending_requests_.GetNextHighestIterator(); | 335 *pending_requests_.GetNextHighestIterator(); |
| 337 pending_requests_.Erase(request); | 336 // Resuming requests asynchronously ensures no side effects, and avoids |
| 338 // Starting requests asynchronously ensures no side effects, and avoids | 337 // resuming a bunch of requests that may be about to be deleted. |
| 339 // starting a bunch of requests that may be about to be deleted. | 338 ResumeRequest(request, RESUME_ASYNC); |
| 340 StartRequest(request, START_ASYNC); | |
| 341 } | 339 } |
| 342 RequestSet unowned_requests; | 340 RequestSet unowned_requests; |
| 343 for (RequestSet::iterator it = in_flight_requests_.begin(); | 341 for (RequestSet::iterator it = in_flight_requests_.begin(); |
| 344 it != in_flight_requests_.end(); ++it) { | 342 it != in_flight_requests_.end(); ++it) { |
| 345 unowned_requests.insert(*it); | 343 unowned_requests.insert(*it); |
| 346 (*it)->set_attributes(kAttributeNone); | 344 (*it)->set_attributes(kAttributeNone); |
| 347 } | 345 } |
| 348 ClearInFlightRequests(); | 346 ClearInFlightRequests(); |
| 349 return unowned_requests; | 347 return unowned_requests; |
| 350 } | 348 } |
| (...skipping 21 matching lines...) Expand all Loading... | |
| 372 } | 370 } |
| 373 } | 371 } |
| 374 | 372 |
| 375 void ReprioritizeRequest(ScheduledResourceRequest* request, | 373 void ReprioritizeRequest(ScheduledResourceRequest* request, |
| 376 RequestPriorityParams old_priority_params, | 374 RequestPriorityParams old_priority_params, |
| 377 RequestPriorityParams new_priority_params) { | 375 RequestPriorityParams new_priority_params) { |
| 378 request->url_request()->SetPriority(new_priority_params.priority); | 376 request->url_request()->SetPriority(new_priority_params.priority); |
| 379 request->set_request_priority_params(new_priority_params); | 377 request->set_request_priority_params(new_priority_params); |
| 380 SetRequestAttributes(request, DetermineRequestAttributes(request)); | 378 SetRequestAttributes(request, DetermineRequestAttributes(request)); |
| 381 if (!pending_requests_.IsQueued(request)) { | 379 if (!pending_requests_.IsQueued(request)) { |
| 382 DCHECK(ContainsKey(in_flight_requests_, request)); | 380 // Request is not waiting to be sent. |
| 383 // Request has already started. | |
| 384 return; | 381 return; |
| 385 } | 382 } |
| 386 | 383 |
| 387 pending_requests_.Erase(request); | 384 pending_requests_.Erase(request); |
| 388 pending_requests_.Insert(request); | 385 pending_requests_.Insert(request); |
| 389 | 386 |
| 390 if (new_priority_params.priority > old_priority_params.priority) { | 387 if (new_priority_params.priority > old_priority_params.priority) { |
| 391 // Check if this request is now able to load at its new priority. | 388 // Check if this request is now able to load at its new priority. |
| 392 LoadAnyStartablePendingRequests(); | 389 LoadAnyStartablePendingRequests(); |
| 393 } | 390 } |
| (...skipping 17 matching lines...) Expand all Loading... | |
| 411 // Clear any special state that we were tracking for this request. | 408 // Clear any special state that we were tracking for this request. |
| 412 SetRequestAttributes(request, kAttributeNone); | 409 SetRequestAttributes(request, kAttributeNone); |
| 413 } | 410 } |
| 414 | 411 |
| 415 void ClearInFlightRequests() { | 412 void ClearInFlightRequests() { |
| 416 in_flight_requests_.clear(); | 413 in_flight_requests_.clear(); |
| 417 in_flight_delayable_count_ = 0; | 414 in_flight_delayable_count_ = 0; |
| 418 total_layout_blocking_count_ = 0; | 415 total_layout_blocking_count_ = 0; |
| 419 } | 416 } |
| 420 | 417 |
| 421 size_t CountRequestsWithAttributes( | 418 size_t CountRequestsWithAttributes(const RequestAttributes attributes) { |
| 422 const RequestAttributes attributes, | |
| 423 ScheduledResourceRequest* current_request) { | |
| 424 size_t matching_request_count = 0; | 419 size_t matching_request_count = 0; |
| 425 for (RequestSet::const_iterator it = in_flight_requests_.begin(); | 420 if (RequestAttributesAreSet(attributes, kAttributeInFlight)) { |
| 426 it != in_flight_requests_.end(); ++it) { | 421 for (RequestSet::const_iterator it = in_flight_requests_.begin(); |
| 427 if (RequestAttributesAreSet((*it)->attributes(), attributes)) | 422 it != in_flight_requests_.end(); ++it) { |
|
mmenke
2016/02/25 18:09:51
Switch to range loops while you're here, on both o
| |
| 428 matching_request_count++; | |
| 429 } | |
| 430 if (!RequestAttributesAreSet(attributes, kAttributeInFlight)) { | |
| 431 bool current_request_is_pending = false; | |
| 432 for (RequestQueue::NetQueue::const_iterator | |
| 433 it = pending_requests_.GetNextHighestIterator(); | |
| 434 it != pending_requests_.End(); ++it) { | |
| 435 if (RequestAttributesAreSet((*it)->attributes(), attributes)) | 423 if (RequestAttributesAreSet((*it)->attributes(), attributes)) |
| 436 matching_request_count++; | 424 matching_request_count++; |
| 437 if (*it == current_request) | |
| 438 current_request_is_pending = true; | |
| 439 } | 425 } |
| 440 // Account for the current request if it is not in one of the lists yet. | 426 } else { |
| 441 if (current_request && | 427 for (RequestSet::const_iterator it = all_requests_.begin(); |
| 442 !ContainsKey(in_flight_requests_, current_request) && | 428 it != all_requests_.end(); ++it) { |
| 443 !current_request_is_pending) { | 429 if (RequestAttributesAreSet((*it)->attributes(), attributes)) |
| 444 if (RequestAttributesAreSet(current_request->attributes(), attributes)) | |
| 445 matching_request_count++; | 430 matching_request_count++; |
| 446 } | 431 } |
| 447 } | 432 } |
| 448 return matching_request_count; | 433 return matching_request_count; |
| 449 } | 434 } |
| 450 | 435 |
| 451 bool RequestAttributesAreSet(RequestAttributes request_attributes, | 436 bool RequestAttributesAreSet(RequestAttributes request_attributes, |
| 452 RequestAttributes matching_attributes) const { | 437 RequestAttributes matching_attributes) const { |
| 453 return (request_attributes & matching_attributes) == matching_attributes; | 438 return (request_attributes & matching_attributes) == matching_attributes; |
| 454 } | 439 } |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 468 | 453 |
| 469 if (RequestAttributesAreSet(attributes, | 454 if (RequestAttributesAreSet(attributes, |
| 470 kAttributeInFlight | kAttributeDelayable)) { | 455 kAttributeInFlight | kAttributeDelayable)) { |
| 471 in_flight_delayable_count_++; | 456 in_flight_delayable_count_++; |
| 472 } | 457 } |
| 473 if (RequestAttributesAreSet(attributes, kAttributeLayoutBlocking)) | 458 if (RequestAttributesAreSet(attributes, kAttributeLayoutBlocking)) |
| 474 total_layout_blocking_count_++; | 459 total_layout_blocking_count_++; |
| 475 | 460 |
| 476 request->set_attributes(attributes); | 461 request->set_attributes(attributes); |
| 477 DCHECK_EQ(CountRequestsWithAttributes( | 462 DCHECK_EQ(CountRequestsWithAttributes( |
| 478 kAttributeInFlight | kAttributeDelayable, request), | 463 kAttributeInFlight | kAttributeDelayable), |
| 479 in_flight_delayable_count_); | 464 in_flight_delayable_count_); |
| 480 DCHECK_EQ(CountRequestsWithAttributes(kAttributeLayoutBlocking, request), | 465 DCHECK_EQ(CountRequestsWithAttributes(kAttributeLayoutBlocking), |
| 481 total_layout_blocking_count_); | 466 total_layout_blocking_count_); |
| 482 } | 467 } |
| 483 | 468 |
| 484 RequestAttributes DetermineRequestAttributes( | 469 RequestAttributes DetermineRequestAttributes( |
| 485 ScheduledResourceRequest* request) { | 470 ScheduledResourceRequest* request) { |
| 486 RequestAttributes attributes = kAttributeNone; | 471 RequestAttributes attributes = kAttributeNone; |
| 487 | 472 |
| 488 if (ContainsKey(in_flight_requests_, request)) | 473 if (ContainsKey(in_flight_requests_, request)) |
| 489 attributes |= kAttributeInFlight; | 474 attributes |= kAttributeInFlight; |
| 490 | 475 |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 524 net::HostPortPair::FromURL((*it)->url_request()->url()); | 509 net::HostPortPair::FromURL((*it)->url_request()->url()); |
| 525 if (active_request_host.Equals(host_port_pair)) { | 510 if (active_request_host.Equals(host_port_pair)) { |
| 526 same_host_count++; | 511 same_host_count++; |
| 527 if (same_host_count >= kMaxNumDelayableRequestsPerHost) | 512 if (same_host_count >= kMaxNumDelayableRequestsPerHost) |
| 528 return true; | 513 return true; |
| 529 } | 514 } |
| 530 } | 515 } |
| 531 return false; | 516 return false; |
| 532 } | 517 } |
| 533 | 518 |
| 534 void StartRequest(ScheduledResourceRequest* request, | 519 void ResumeRequest(ScheduledResourceRequest* request, |
| 535 StartMode start_mode) { | 520 ResumeMode resume_mode) { |
| 521 DCHECK(pending_requests_.IsQueued(request)); | |
| 522 pending_requests_.Erase(request); | |
| 536 InsertInFlightRequest(request); | 523 InsertInFlightRequest(request); |
| 537 request->Start(start_mode); | 524 request->Resume(resume_mode); |
| 538 } | 525 } |
| 539 | 526 |
| 540 // ShouldStartRequest is the main scheduling algorithm. | 527 // ShouldStartRequest is the main scheduling algorithm. |
| 541 // | 528 // |
| 542 // Requests are evaluated on five attributes: | 529 // Requests are evaluated on five attributes: |
| 543 // | 530 // |
| 544 // 1. Non-delayable requests: | 531 // 1. Non-delayable requests: |
| 545 // * Synchronous requests. | 532 // * Synchronous requests. |
| 546 // * Non-HTTP[S] requests. | 533 // * Non-HTTP[S] requests. |
| 547 // | 534 // |
| (...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 670 // 3) We do not start the request, same as above, but StartRequest() tells | 657 // 3) We do not start the request, same as above, but StartRequest() tells |
| 671 // us there's no point in checking any further requests. | 658 // us there's no point in checking any further requests. |
| 672 RequestQueue::NetQueue::iterator request_iter = | 659 RequestQueue::NetQueue::iterator request_iter = |
| 673 pending_requests_.GetNextHighestIterator(); | 660 pending_requests_.GetNextHighestIterator(); |
| 674 | 661 |
| 675 while (request_iter != pending_requests_.End()) { | 662 while (request_iter != pending_requests_.End()) { |
| 676 ScheduledResourceRequest* request = *request_iter; | 663 ScheduledResourceRequest* request = *request_iter; |
| 677 ShouldStartReqResult query_result = ShouldStartRequest(request); | 664 ShouldStartReqResult query_result = ShouldStartRequest(request); |
| 678 | 665 |
| 679 if (query_result == START_REQUEST) { | 666 if (query_result == START_REQUEST) { |
| 680 pending_requests_.Erase(request); | 667 ResumeRequest(request, RESUME_ASYNC); |
| 681 StartRequest(request, START_ASYNC); | |
| 682 | 668 |
| 683 // StartRequest can modify the pending list, so we (re)start evaluation | 669 // StartRequest can modify the pending list, so we (re)start evaluation |
| 684 // from the currently highest priority request. Avoid copying a singular | 670 // from the currently highest priority request. Avoid copying a singular |
| 685 // iterator, which would trigger undefined behavior. | 671 // iterator, which would trigger undefined behavior. |
| 686 if (pending_requests_.GetNextHighestIterator() == | 672 if (pending_requests_.GetNextHighestIterator() == |
| 687 pending_requests_.End()) | 673 pending_requests_.End()) |
| 688 break; | 674 break; |
| 689 request_iter = pending_requests_.GetNextHighestIterator(); | 675 request_iter = pending_requests_.GetNextHighestIterator(); |
| 690 } else if (query_result == DO_NOT_START_REQUEST_AND_KEEP_SEARCHING) { | 676 } else if (query_result == DO_NOT_START_REQUEST_AND_KEEP_SEARCHING) { |
| 691 ++request_iter; | 677 ++request_iter; |
| 692 continue; | 678 continue; |
| 693 } else { | 679 } else { |
| 694 DCHECK(query_result == DO_NOT_START_REQUEST_AND_STOP_SEARCHING); | 680 DCHECK(query_result == DO_NOT_START_REQUEST_AND_STOP_SEARCHING); |
| 695 break; | 681 break; |
| 696 } | 682 } |
| 697 } | 683 } |
| 698 } | 684 } |
| 699 | 685 |
| 700 bool is_loaded_; | 686 bool is_loaded_; |
| 701 // Tracks if the main HTML parser has reached the body which marks the end of | 687 // Tracks if the main HTML parser has reached the body which marks the end of |
| 702 // layout-blocking resources. | 688 // layout-blocking resources. |
| 703 bool has_html_body_; | 689 bool has_html_body_; |
| 704 bool using_spdy_proxy_; | 690 bool using_spdy_proxy_; |
| 691 RequestSet all_requests_; | |
|
mmenke
2016/02/25 18:09:51
Hrm... I really don't like keeping around a third
| |
| 705 RequestQueue pending_requests_; | 692 RequestQueue pending_requests_; |
| 706 RequestSet in_flight_requests_; | 693 RequestSet in_flight_requests_; |
| 707 ResourceScheduler* scheduler_; | 694 ResourceScheduler* scheduler_; |
| 708 // The number of delayable in-flight requests. | 695 // The number of delayable in-flight requests. |
| 709 size_t in_flight_delayable_count_; | 696 size_t in_flight_delayable_count_; |
| 710 // The number of layout-blocking in-flight requests. | 697 // The number of layout-blocking in-flight requests. |
| 711 size_t total_layout_blocking_count_; | 698 size_t total_layout_blocking_count_; |
| 712 }; | 699 }; |
| 713 | 700 |
| 714 ResourceScheduler::ResourceScheduler() | 701 ResourceScheduler::ResourceScheduler() |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 787 client_id, url_request, this, | 774 client_id, url_request, this, |
| 788 RequestPriorityParams(url_request->priority(), 0), is_async)); | 775 RequestPriorityParams(url_request->priority(), 0), is_async)); |
| 789 | 776 |
| 790 ClientMap::iterator it = client_map_.find(client_id); | 777 ClientMap::iterator it = client_map_.find(client_id); |
| 791 if (it == client_map_.end()) { | 778 if (it == client_map_.end()) { |
| 792 // There are several ways this could happen: | 779 // There are several ways this could happen: |
| 793 // 1. <a ping> requests don't have a route_id. | 780 // 1. <a ping> requests don't have a route_id. |
| 794 // 2. Most unittests don't send the IPCs needed to register Clients. | 781 // 2. Most unittests don't send the IPCs needed to register Clients. |
| 795 // 3. The tab is closed while a RequestResource IPC is in flight. | 782 // 3. The tab is closed while a RequestResource IPC is in flight. |
| 796 unowned_requests_.insert(request.get()); | 783 unowned_requests_.insert(request.get()); |
| 797 request->Start(START_SYNC); | |
| 798 return std::move(request); | 784 return std::move(request); |
| 799 } | 785 } |
| 800 | 786 |
| 801 Client* client = it->second; | 787 Client* client = it->second; |
| 802 client->ScheduleRequest(url_request, request.get()); | 788 client->ScheduleRequest(url_request, request.get()); |
| 803 return std::move(request); | 789 return std::move(request); |
| 804 } | 790 } |
| 805 | 791 |
| 792 bool ResourceScheduler::ShouldSendRequest(ScheduledResourceRequest* request) { | |
|
mmenke
2016/02/25 18:09:51
Per earlier comment, the number of side effects th
| |
| 793 DCHECK(CalledOnValidThread()); | |
| 794 ClientMap::iterator client_it = client_map_.find(request->client_id()); | |
| 795 if (client_it == client_map_.end()) { | |
|
mmenke
2016/02/25 18:09:51
Think this warrants a comment.
| |
| 796 return true; | |
| 797 } | |
|
mmenke
2016/02/25 18:09:51
nit: Remove braces.
| |
| 798 | |
| 799 Client* client = client_it->second; | |
| 800 return client->ShouldSendRequest(request); | |
| 801 } | |
| 802 | |
| 806 void ResourceScheduler::RemoveRequest(ScheduledResourceRequest* request) { | 803 void ResourceScheduler::RemoveRequest(ScheduledResourceRequest* request) { |
| 807 DCHECK(CalledOnValidThread()); | 804 DCHECK(CalledOnValidThread()); |
| 808 if (ContainsKey(unowned_requests_, request)) { | 805 if (ContainsKey(unowned_requests_, request)) { |
| 809 unowned_requests_.erase(request); | 806 unowned_requests_.erase(request); |
| 810 return; | 807 return; |
| 811 } | 808 } |
| 812 | 809 |
| 813 ClientMap::iterator client_it = client_map_.find(request->client_id()); | 810 ClientMap::iterator client_it = client_map_.find(request->client_id()); |
| 814 if (client_it == client_map_.end()) { | 811 if (client_it == client_map_.end()) { |
| 815 return; | 812 return; |
| (...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 957 client->ReprioritizeRequest(scheduled_resource_request, old_priority_params, | 954 client->ReprioritizeRequest(scheduled_resource_request, old_priority_params, |
| 958 new_priority_params); | 955 new_priority_params); |
| 959 } | 956 } |
| 960 | 957 |
| 961 ResourceScheduler::ClientId ResourceScheduler::MakeClientId( | 958 ResourceScheduler::ClientId ResourceScheduler::MakeClientId( |
| 962 int child_id, int route_id) { | 959 int child_id, int route_id) { |
| 963 return (static_cast<ResourceScheduler::ClientId>(child_id) << 32) | route_id; | 960 return (static_cast<ResourceScheduler::ClientId>(child_id) << 32) | route_id; |
| 964 } | 961 } |
| 965 | 962 |
| 966 } // namespace content | 963 } // namespace content |
| OLD | NEW |