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).