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

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

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

Powered by Google App Engine
This is Rietveld 408576698