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

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: Track background requests 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 "content/browser/renderer_host/resource_loader.h"
9 #include "net/base/request_priority.h"
10 #include "net/url_request/url_request.h"
11
12 namespace content {
13
14 namespace {
15
16 ResourceScheduler::ClientId MakeClientId(int child_id, int route_id) {
17 return (static_cast<ResourceScheduler::ClientId>(child_id) << 32) | route_id;
18 }
19
20 ResourceScheduler::BackgroundRequestId MakeBackgroundRequestId(int child_id,
21 int request_id) {
22 return (static_cast<ResourceScheduler::ClientId>(child_id) << 32)
23 | request_id;
24 }
25
26 } // unnamed namespace
27
28 // Tracks a background request issued by a tab. <a ping> is an example.
29 // Currently, these are loaded immediately, with no scheduling.
30 class ResourceScheduler::BackgroundLoadHandle : public LoadHandle {
31 public:
32 BackgroundLoadHandle(BackgroundRequestId request_id,
33 const linked_ptr<ResourceLoader>& loader,
34 ResourceScheduler* scheduler)
35 : request_id_(request_id),
36 loader_(loader),
37 scheduler_(scheduler) {
38 }
39
40 virtual ~BackgroundLoadHandle() {
41 scheduler_->RemoveBackgroundLoad(request_id_);
42 }
43
44 virtual linked_ptr<ResourceLoader> loader() OVERRIDE { return loader_; }
45
46 BackgroundRequestId request_id_;
willchan no longer on Chromium 2012/12/03 02:30:16 private:
47 linked_ptr<ResourceLoader> loader_;
48 ResourceScheduler* scheduler_;
49 };
50
51 // Represents a normal resource load.
52 class ResourceScheduler::ScheduledLoadHandle : public LoadHandle {
53 public:
54 ScheduledLoadHandle(ClientId client_id,
55 int request_id,
56 const linked_ptr<ResourceLoader>& loader,
57 ResourceScheduler* scheduler)
58 : client_id_(client_id),
59 request_id_(request_id),
60 loader_(loader),
61 scheduler_(scheduler) {
62 }
63
64 virtual ~ScheduledLoadHandle() {
65 scheduler_->RemoveLoad(client_id_, request_id_);
66 }
67
68 virtual linked_ptr<ResourceLoader> loader() OVERRIDE { return loader_; }
69
70 private:
71 ClientId client_id_;
72 int request_id_;
73 linked_ptr<ResourceLoader> loader_;
74 ResourceScheduler* scheduler_;
75 };
76
77 ResourceScheduler::ResourceScheduler() {
78 }
79
80 ResourceScheduler::~ResourceScheduler() {
81 }
82
83 scoped_ptr<ResourceScheduler::LoadHandle> ResourceScheduler::ScheduleLoad(
84 int child_id,
85 int route_id,
86 int request_id,
87 const linked_ptr<ResourceLoader>& loader) {
88 if (route_id == 0) {
89 // <a ping> requests don't have a route_id.
90 BackgroundRequestId background_id = MakeBackgroundRequestId(child_id,
91 request_id);
92 background_requests_.insert(background_id);
93 loader->StartRequest();
willchan no longer on Chromium 2012/12/03 02:30:16 I'm not sure if all URLRequestJobs complete asynch
James Simonsen 2012/12/05 01:52:45 No longer an issue. We don't hang on to it any mor
94 scoped_ptr<LoadHandle> handle(new BackgroundLoadHandle(
95 background_id, loader, this));
96 return handle.Pass();
97 }
98
99 ClientId client_id = MakeClientId(child_id, route_id);
100 CHECK(ContainsKey(client_map_, client_id));
101 Client* client = client_map_[client_id];
102 DCHECK(!client->closed);
103 scoped_ptr<LoadHandle> handle(new ScheduledLoadHandle(
104 client_id, request_id, loader, this));
105 Request request = { request_id, loader.get() };
106
107 if (loader->request()->priority() < net::MEDIUM &&
108 !client->in_flight_requests.empty() && !client->has_painted) {
109 client->pending_requests.push_back(request);
110 return handle.Pass();
111 }
112
113 StartRequest(request, client);
114 return handle.Pass();
115 }
116
117 void ResourceScheduler::RemoveLoad(ClientId client_id, int request_id) {
118 DCHECK(ContainsKey(client_map_, client_id));
119 Client* client = client_map_[client_id];
120 RequestIdSet::iterator it = client->in_flight_requests.find(request_id);
121 if (it == client->in_flight_requests.end()) {
122 bool removed = false;
123 RequestQueue::iterator queue_it;
124 for (queue_it = client->pending_requests.begin();
125 queue_it != client->pending_requests.end(); ++queue_it) {
126 if (queue_it->request_id == request_id) {
127 client->pending_requests.erase(queue_it);
128 removed = true;
129 break;
130 }
131 }
132 DCHECK(removed);
133 DCHECK(!ContainsKey(client->in_flight_requests, request_id));
134 } else {
135 bool erased = client->in_flight_requests.erase(request_id);
136 DCHECK(erased);
137 }
138
139 if (client->closed) {
140 if (client->in_flight_requests.empty()
141 && client->pending_requests.empty()) {
142 delete client;
143 client_map_.erase(client_id);
144 }
145 } else if (client->in_flight_requests.empty()) {
146 LoadPendingRequests(client);
147 }
148 }
149
150 void ResourceScheduler::RemoveBackgroundLoad(BackgroundRequestId request_id) {
151 bool erased = background_requests_.erase(request_id);
152 DCHECK(erased);
153 }
154
155 void ResourceScheduler::OnCreate(int child_id, int route_id) {
156 ClientId client_id = MakeClientId(child_id, route_id);
157 DCHECK(!ContainsKey(client_map_, client_id));
158 client_map_[client_id] = new Client;
159 }
160
161 void ResourceScheduler::OnNavigate(int child_id, int route_id) {
162 ClientId client_id = MakeClientId(child_id, route_id);
163 DCHECK(ContainsKey(client_map_, client_id));
164 Client* client = client_map_[client_id];
165 client->has_painted = false;
166 }
167
168 void ResourceScheduler::OnPaint(int child_id, int route_id) {
169 ClientId client_id = MakeClientId(child_id, route_id);
170 DCHECK(ContainsKey(client_map_, client_id));
171 Client* client = client_map_[client_id];
172 if (!client->has_painted) {
173 client->has_painted = true;
174 LoadPendingRequests(client);
175 }
176 }
177
178 void ResourceScheduler::OnDestroy(int child_id, int route_id) {
179 ClientId client_id = MakeClientId(child_id, route_id);
180 DCHECK(ContainsKey(client_map_, client_id));
181 Client* client = client_map_[client_id];
182 if (client->pending_requests.empty() && client->in_flight_requests.empty()) {
183 delete client;
184 client_map_.erase(client_id);
185 } else {
186 client->closed = true;
187 }
188 }
189
190 void ResourceScheduler::StartRequest(Request request, Client* client) {
191 client->in_flight_requests.insert(request.request_id);
192 request.loader->StartRequest();
193 }
194
195 void ResourceScheduler::LoadPendingRequests(Client* client) {
196 RequestQueue::iterator it;
197 for (it = client->pending_requests.begin();
198 it != client->pending_requests.end(); ++it) {
199 StartRequest(*it, client);
200 }
201 client->pending_requests.clear();
202 }
203
204 ResourceScheduler::Client::Client()
205 : has_painted(false),
206 closed(false) {
207 }
208
209 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698