Upstream version 11.39.266.0
[platform/framework/web/crosswalk.git] / src / ui / file_manager / image_loader / worker.js
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.
4
5 'use strict';
6
7 /**
8  * Worker for requests. Fetches requests from a queue and processes them
9  * synchronously, taking into account priorities. The highest priority is 0.
10  */
11 function Worker() {
12   /**
13    * List of requests waiting to be checked. If these items are available in
14    * cache, then they are processed immediately after starting the worker.
15    * However, if they have to be downloaded, then these requests are moved
16    * to pendingRequests_.
17    *
18    * @type {Array.<Request>}
19    * @private
20    */
21   this.newRequests_ = [];
22
23   /**
24    * List of pending requests for images to be downloaded.
25    * @type {Array.<Request>}
26    * @private
27    */
28   this.pendingRequests_ = [];
29
30   /**
31    * List of requests being processed.
32    * @type {Array.<Request>}
33    * @private
34    */
35   this.activeRequests_ = [];
36
37   /**
38    * Hash array of requests being added to the queue, but not finalized yet.
39    * @type {Object}
40    * @private
41    */
42   this.requests_ = {};
43
44   /**
45    * If the worker has been started.
46    * @type {boolean}
47    * @private
48    */
49   this.started_ = false;
50 }
51
52 /**
53  * Maximum download requests to be run in parallel.
54  * @type {number}
55  * @const
56  */
57 Worker.MAXIMUM_IN_PARALLEL = 5;
58
59 /**
60  * Adds a request to the internal priority queue and executes it when requests
61  * with higher priorities are finished. If the result is cached, then it is
62  * processed immediately once the worker is started.
63  *
64  * @param {Request} request Request object.
65  */
66 Worker.prototype.add = function(request) {
67   if (!this.started_) {
68     this.newRequests_.push(request);
69     this.requests_[request.getId()] = request;
70     return;
71   }
72
73   // Enqueue the request, since already started.
74   this.pendingRequests_.push(request);
75   this.sortPendingRequests_();
76
77   this.continue_();
78 };
79
80 /**
81  * Removes a request from the worker (if exists).
82  * @param {string} requestId Unique ID of the request.
83  */
84 Worker.prototype.remove = function(requestId) {
85   var request = this.requests_[requestId];
86   if (!request)
87     return;
88
89   // Remove from the internal queues with pending tasks.
90   var newIndex = this.pendingRequests_.indexOf(request);
91   if (newIndex != -1)
92     this.newRequests_.splice(newIndex, 1);
93   var pendingIndex = this.pendingRequests_.indexOf(request);
94   if (pendingIndex != -1)
95     this.pendingRequests_.splice(pendingIndex, 1);
96
97   // Cancel the request.
98   request.cancel();
99   delete this.requests_[requestId];
100 };
101
102 /**
103  * Starts handling requests.
104  */
105 Worker.prototype.start = function() {
106   this.started_ = true;
107
108   // Process tasks added before worker has been started.
109   this.pendingRequests_ = this.newRequests_;
110   this.sortPendingRequests_();
111   this.newRequests_ = [];
112
113   // Start serving enqueued requests.
114   this.continue_();
115 };
116
117 /**
118  * Sorts pending requests by priorities.
119  * @private
120  */
121 Worker.prototype.sortPendingRequests_ = function() {
122   this.pendingRequests_.sort(function(a, b) {
123     return a.getPriority() - b.getPriority();
124   });
125 };
126
127 /**
128  * Processes pending requests from the queue. There is no guarantee that
129  * all of the tasks will be processed at once.
130  *
131  * @private
132  */
133 Worker.prototype.continue_ = function() {
134   // Run only up to MAXIMUM_IN_PARALLEL in the same time.
135   while (this.pendingRequests_.length &&
136          this.activeRequests_.length < Worker.MAXIMUM_IN_PARALLEL) {
137     var request = this.pendingRequests_.shift();
138     this.activeRequests_.push(request);
139
140     // Try to load from cache. If doesn't exist, then download.
141     request.loadFromCacheAndProcess(
142         this.finish_.bind(this, request),
143         function(currentRequest) {
144           currentRequest.downloadAndProcess(
145               this.finish_.bind(this, currentRequest));
146         }.bind(this, request));
147   }
148 };
149
150 /**
151  * Handles finished requests.
152  *
153  * @param {Request} request Finished request.
154  * @private
155  */
156 Worker.prototype.finish_ = function(request) {
157   var index = this.activeRequests_.indexOf(request);
158   if (index < 0)
159     console.warn('Request not found.');
160   this.activeRequests_.splice(index, 1);
161   delete this.requests_[request.getId()];
162
163   // Continue handling the most important requests (if started).
164   if (this.started_)
165     this.continue_();
166 };