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

Side by Side Diff: content/browser/renderer_host/resource_scheduler.cc

Issue 11270027: Add a ResourceScheduler to ResourceDispatcherHost. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Almost no linked_ptrs Created 8 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
(Empty)
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
3 // found in the LICENSE file.
4
5 #include "content/browser/renderer_host/resource_scheduler.h"
6
7 #include "base/stl_util.h"
8 #include "net/base/request_priority.h"
9 #include "net/url_request/url_request.h"
10
11 namespace content {
12
13 namespace {
14
15 ResourceScheduler::ClientId MakeClientId(int child_id, int route_id) {
16 return (static_cast<ResourceScheduler::ClientId>(child_id) << 32) | route_id;
17 }
18
19 } // unnamed namespace
20
21 class LoadHandleImpl : public ResourceScheduler::LoadHandle {
22 public:
23 LoadHandleImpl(ResourceScheduler::SchedulerId scheduler_id,
24 ResourceScheduler::ClientId client_id,
25 ResourceScheduler* scheduler)
26 : scheduler_id_(scheduler_id),
27 client_id_(client_id),
28 scheduler_(scheduler) {
29 }
30
31 virtual ~LoadHandleImpl() {
32 scheduler_->RemoveLoad(scheduler_id_, client_id_);
33 }
34
35 private:
36 ResourceScheduler::SchedulerId scheduler_id_;
37 ResourceScheduler::ClientId client_id_;
38 ResourceScheduler* scheduler_;
39 };
40
41 ResourceScheduler::ResourceScheduler()
42 : next_scheduler_id_(0) {
43 }
44
45 ResourceScheduler::~ResourceScheduler() {
46 }
47
48 scoped_ptr<ResourceScheduler::LoadHandle> ResourceScheduler::ScheduleLoad(
49 int child_id,
50 int route_id,
51 Loadable* loadable) {
52 SchedulerId scheduler_id = ++next_scheduler_id_;
53 ClientId client_id = MakeClientId(child_id, route_id);
54 scoped_ptr<LoadHandle> handle(new LoadHandleImpl(
55 scheduler_id, client_id, this));
56
57 if (route_id == 0 || !ContainsKey(client_map_, client_id)) {
58 // <a ping> requests don't belong to a specific page. Most tests don't call
59 // OnCreate et. al. as needed to register Clients either.
60 unowned_requests_.insert(scheduler_id);
61 loadable->StartRequest();
62 return handle.Pass();
63 }
64
65 Client* client = client_map_[client_id];
66 DCHECK(!client->has_closed);
67 Request request = { scheduler_id, loadable };
68
69 if (loadable->url_request()->priority() < net::MEDIUM &&
70 !client->in_flight_requests.empty() && !client->has_painted) {
71 client->pending_requests.push_back(request);
72 } else {
73 StartRequest(request, client);
74 }
75 return handle.Pass();
76 }
77
78 void ResourceScheduler::RemoveLoad(SchedulerId scheduler_id,
79 ClientId client_id) {
80 if (ContainsKey(unowned_requests_, scheduler_id)) {
81 unowned_requests_.erase(scheduler_id);
82 return;
83 }
84
85 DCHECK(ContainsKey(client_map_, client_id));
86 Client* client = client_map_[client_id];
87 SchedulerIdSet::iterator it = client->in_flight_requests.find(scheduler_id);
88 if (it == client->in_flight_requests.end()) {
89 bool removed = false;
90 RequestQueue::iterator queue_it;
91 for (queue_it = client->pending_requests.begin();
92 queue_it != client->pending_requests.end(); ++queue_it) {
93 if (queue_it->scheduler_id == scheduler_id) {
94 client->pending_requests.erase(queue_it);
95 removed = true;
96 break;
97 }
98 }
99 DCHECK(removed);
100 DCHECK(!ContainsKey(client->in_flight_requests, scheduler_id));
101 } else {
102 size_t erased = client->in_flight_requests.erase(scheduler_id);
103 DCHECK(erased);
104 }
105
106 if (client->has_closed) {
107 if (client->in_flight_requests.empty()
108 && client->pending_requests.empty()) {
109 delete client;
110 client_map_.erase(client_id);
111 }
112 } else if (client->in_flight_requests.empty()) {
113 LoadPendingRequests(client);
114 }
115 }
116
117 void ResourceScheduler::OnCreate(int child_id, int route_id) {
118 ClientId client_id = MakeClientId(child_id, route_id);
119 DCHECK(!ContainsKey(client_map_, client_id));
120 client_map_[client_id] = new Client;
121 }
122
123 void ResourceScheduler::OnNavigate(int child_id, int route_id) {
124 ClientId client_id = MakeClientId(child_id, route_id);
125 DCHECK(ContainsKey(client_map_, client_id));
126 Client* client = client_map_[client_id];
127 client->has_painted = false;
128 }
129
130 void ResourceScheduler::OnPaint(int child_id, int route_id) {
131 ClientId client_id = MakeClientId(child_id, route_id);
132 DCHECK(ContainsKey(client_map_, client_id));
133 Client* client = client_map_[client_id];
134 if (!client->has_painted) {
135 client->has_painted = true;
136 LoadPendingRequests(client);
137 }
138 }
139
140 void ResourceScheduler::OnDestroy(int child_id, int route_id) {
141 ClientId client_id = MakeClientId(child_id, route_id);
142 DCHECK(ContainsKey(client_map_, client_id));
143 Client* client = client_map_[client_id];
144 if (client->pending_requests.empty() && client->in_flight_requests.empty()) {
145 delete client;
146 client_map_.erase(client_id);
147 } else {
148 client->has_closed = true;
149 }
150 }
151
152 void ResourceScheduler::StartRequest(Request request, Client* client) {
153 client->in_flight_requests.insert(request.scheduler_id);
154 request.loadable->StartRequest();
155 }
156
157 void ResourceScheduler::LoadPendingRequests(Client* client) {
158 RequestQueue::iterator it;
159 for (it = client->pending_requests.begin();
160 it != client->pending_requests.end(); ++it) {
161 StartRequest(*it, client);
162 }
163 client->pending_requests.clear();
164 }
165
166 ResourceScheduler::Client::Client()
167 : has_painted(false),
168 has_closed(false) {
169 }
170
171 ResourceScheduler::Client::~Client() {
172 }
173
174 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698