1 // Copyright 2013 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.
6 * Scheduler for requests. Fetches requests from a queue and processes them
7 * synchronously, taking into account priorities. The highest priority is 0.
10 function Scheduler() {
12 * List of requests waiting to be checked. If these items are available in
13 * cache, then they are processed immediately after starting the scheduler.
14 * However, if they have to be downloaded, then these requests are moved
15 * to pendingRequests_.
17 * @type {Array.<Request>}
20 this.newRequests_
= [];
23 * List of pending requests for images to be downloaded.
24 * @type {Array.<Request>}
27 this.pendingRequests_
= [];
30 * List of requests being processed.
31 * @type {Array.<Request>}
34 this.activeRequests_
= [];
37 * Hash array of requests being added to the queue, but not finalized yet.
44 * If the scheduler has been started.
48 this.started_
= false;
52 * Maximum download requests to be run in parallel.
56 Scheduler
.MAXIMUM_IN_PARALLEL
= 5;
59 * Adds a request to the internal priority queue and executes it when requests
60 * with higher priorities are finished. If the result is cached, then it is
61 * processed immediately once the scheduler is started.
63 * @param {Request} request Request object.
65 Scheduler
.prototype.add = function(request
) {
67 this.newRequests_
.push(request
);
68 this.requests_
[request
.getId()] = request
;
72 // Enqueue the request, since already started.
73 this.pendingRequests_
.push(request
);
74 this.sortPendingRequests_();
80 * Removes a request from the scheduler (if exists).
81 * @param {string} requestId Unique ID of the request.
83 Scheduler
.prototype.remove = function(requestId
) {
84 var request
= this.requests_
[requestId
];
88 // Remove from the internal queues with pending tasks.
89 var newIndex
= this.pendingRequests_
.indexOf(request
);
91 this.newRequests_
.splice(newIndex
, 1);
92 var pendingIndex
= this.pendingRequests_
.indexOf(request
);
93 if (pendingIndex
!= -1)
94 this.pendingRequests_
.splice(pendingIndex
, 1);
96 // Cancel the request.
98 delete this.requests_
[requestId
];
102 * Starts handling requests.
104 Scheduler
.prototype.start = function() {
105 this.started_
= true;
107 // Process tasks added before scheduler has been started.
108 this.pendingRequests_
= this.newRequests_
;
109 this.sortPendingRequests_();
110 this.newRequests_
= [];
112 // Start serving enqueued requests.
117 * Sorts pending requests by priorities.
120 Scheduler
.prototype.sortPendingRequests_ = function() {
121 this.pendingRequests_
.sort(function(a
, b
) {
122 return a
.getPriority() - b
.getPriority();
127 * Processes pending requests from the queue. There is no guarantee that
128 * all of the tasks will be processed at once.
132 Scheduler
.prototype.continue_ = function() {
133 // Run only up to MAXIMUM_IN_PARALLEL in the same time.
134 while (this.pendingRequests_
.length
&&
135 this.activeRequests_
.length
< Scheduler
.MAXIMUM_IN_PARALLEL
) {
136 var request
= this.pendingRequests_
.shift();
137 this.activeRequests_
.push(request
);
139 // Try to load from cache. If doesn't exist, then download.
140 request
.loadFromCacheAndProcess(
141 this.finish_
.bind(this, request
),
142 function(currentRequest
) {
143 currentRequest
.downloadAndProcess(
144 this.finish_
.bind(this, currentRequest
));
145 }.bind(this, request
));
150 * Handles finished requests.
152 * @param {Request} request Finished request.
155 Scheduler
.prototype.finish_ = function(request
) {
156 var index
= this.activeRequests_
.indexOf(request
);
158 console
.warn('Request not found.');
159 this.activeRequests_
.splice(index
, 1);
160 delete this.requests_
[request
.getId()];
162 // Continue handling the most important requests (if started).