OLD | NEW |
---|---|
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 'use strict'; | 5 'use strict'; |
6 | 6 |
7 /** | 7 /** |
8 * Namespace for async utility functions. | 8 * Namespace for async utility functions. |
9 */ | 9 */ |
10 var AsyncUtil = {}; | 10 var AsyncUtil = {}; |
(...skipping 25 matching lines...) Expand all Loading... | |
36 callback(iterationCompletionCallback, element, index, array); | 36 callback(iterationCompletionCallback, element, index, array); |
37 }.bind(null, array[i], i)); | 37 }.bind(null, array[i], i)); |
38 } | 38 } |
39 queue.run(function(iterationCompletionCallback) { | 39 queue.run(function(iterationCompletionCallback) { |
40 completionCallback(); // Don't pass iteration completion callback. | 40 completionCallback(); // Don't pass iteration completion callback. |
41 }); | 41 }); |
42 }; | 42 }; |
43 | 43 |
44 /** | 44 /** |
45 * Creates a class for executing several asynchronous closures in a fifo queue. | 45 * Creates a class for executing several asynchronous closures in a fifo queue. |
46 * Added tasks will be started in order they were added. Tasks are run | |
47 * concurrently. At most, |limit| jobs will be run at the same time. | |
48 * | |
49 * @param {number} limit The number of jobs to run at the same time. | |
50 * @constructor | |
51 */ | |
52 AsyncUtil.ConcurrentQueue = function(limit) { | |
53 console.assert(limit > 0, '|limit| must be larger than 2'); | |
54 | |
55 this.limit_ = limit; | |
56 this.addedTasks_ = []; | |
57 this.pendingTasks_ = []; | |
58 this.isCancelled_ = false; | |
59 | |
60 Object.seal(this); | |
61 }; | |
62 | |
63 /** | |
64 * @return {boolean} True when a task is running, otherwise false. | |
65 */ | |
66 AsyncUtil.ConcurrentQueue.prototype.isRunning = function() { | |
67 return this.pendingTasks_.length !== 0; | |
68 }; | |
69 | |
70 /** | |
71 * @return {number} Number of waiting tasks. | |
72 */ | |
73 AsyncUtil.ConcurrentQueue.prototype.getWaitingTasksCount = function() { | |
74 return this.addedTasks_.length; | |
75 }; | |
76 | |
77 /** | |
78 * @return {boolean} Number of running tasks. | |
79 */ | |
80 AsyncUtil.ConcurrentQueue.prototype.getRunningTasksCount = function() { | |
81 return this.pendingTasks_.length; | |
82 }; | |
83 | |
84 /** | |
85 * Enqueues a closure to be executed. | |
86 * @param {function(function(callback, isCancelled=))} closure Closure with a | |
87 * completion callback to be executed. | |
88 */ | |
89 AsyncUtil.ConcurrentQueue.prototype.run = function(closure) { | |
90 if (this.isCancelled_) { | |
91 console.error('Queue is calcelled. Cannot add a new task.'); | |
92 return; | |
93 } | |
94 | |
95 this.addedTasks_.push(closure); | |
96 this.continue_(); | |
97 return; | |
hirono
2014/05/26 09:19:42
nit: Is it needed?
yoshiki
2014/05/26 09:36:33
Done.
| |
98 }; | |
99 | |
100 /** | |
101 * Cancels the queue. It removes all the not-run (yet) tasks. Note that this | |
102 * does NOT stop tasks currently running. | |
103 */ | |
104 AsyncUtil.ConcurrentQueue.prototype.cancel = function() { | |
105 this.isCancelled_ = true; | |
106 this.addedTasks_ = []; | |
107 }; | |
108 | |
109 /** | |
110 * @return {boolean} True when the queue have been requested to cancel or is | |
111 * already cancelled. Otherwise false. | |
112 */ | |
113 AsyncUtil.ConcurrentQueue.prototype.isCancelled = function() { | |
114 return this.isCancelled_; | |
115 }; | |
116 | |
117 /** | |
118 * Runs the next tasks if available. | |
119 * @private | |
120 */ | |
121 AsyncUtil.ConcurrentQueue.prototype.continue_ = function() { | |
122 if (this.addedTasks_.length === 0) | |
123 return; | |
124 | |
125 console.assert( | |
126 this.pendingTasks_.length <= this.limit_, | |
127 'Too many jobs are running (' + this.pendingTasks_.length + ')'); | |
128 | |
129 if (this.pendingTasks_.length >= this.limit_) | |
130 return; | |
131 | |
132 // Run the next closure. | |
133 var closure = this.addedTasks_.shift(); | |
134 this.pendingTasks_.push(closure); | |
135 closure(this.onTaskFinished_.bind(this, closure), this.isCancelled_); | |
136 | |
137 this.continue_(); | |
138 }; | |
139 | |
140 /** | |
141 * Called when a task is finished. Removes the tasks from pending task list. | |
142 * @private | |
143 */ | |
144 AsyncUtil.ConcurrentQueue.prototype.onTaskFinished_ = function(closure) { | |
145 var index = this.pendingTasks_.indexOf(closure); | |
146 console.assert(index >= 0, 'Invalid task is finished'); | |
147 this.pendingTasks_.splice(index, 1); | |
148 | |
149 this.continue_(); | |
150 }; | |
151 | |
152 /** | |
153 * Creates a class for executing several asynchronous closures in a fifo queue. | |
46 * Added tasks will be executed sequentially in order they were added. | 154 * Added tasks will be executed sequentially in order they were added. |
47 * | 155 * |
48 * @constructor | 156 * @constructor |
157 * @extends {AsyncUtil.ConcurrentQueue} | |
49 */ | 158 */ |
50 AsyncUtil.Queue = function() { | 159 AsyncUtil.Queue = function() { |
51 this.running_ = false; | 160 AsyncUtil.ConcurrentQueue.call(this, 1); |
52 this.closures_ = []; | |
53 }; | 161 }; |
54 | 162 |
55 /** | 163 AsyncUtil.Queue.prototype.__proto__ = AsyncUtil.ConcurrentQueue.prototype; |
56 * @return {boolean} True when a task is running, otherwise false. | |
57 */ | |
58 AsyncUtil.Queue.prototype.isRunning = function() { | |
59 return this.running_; | |
60 }; | |
61 | |
62 /** | |
63 * Enqueues a closure to be executed. | |
64 * @param {function(function())} closure Closure with a completion callback to | |
65 * be executed. | |
66 */ | |
67 AsyncUtil.Queue.prototype.run = function(closure) { | |
68 this.closures_.push(closure); | |
69 if (!this.running_) | |
70 this.continue_(); | |
71 }; | |
72 | |
73 /** | |
74 * Serves the next closure from the queue. | |
75 * @private | |
76 */ | |
77 AsyncUtil.Queue.prototype.continue_ = function() { | |
78 if (!this.closures_.length) { | |
79 this.running_ = false; | |
80 return; | |
81 } | |
82 | |
83 // Run the next closure. | |
84 this.running_ = true; | |
85 var closure = this.closures_.shift(); | |
86 closure(this.continue_.bind(this)); | |
87 }; | |
88 | |
89 /** | |
90 * Cancels all pending tasks. Note that this does NOT cancel the task running | |
91 * currently. | |
92 */ | |
93 AsyncUtil.Queue.prototype.cancel = function() { | |
94 this.closures_ = []; | |
95 }; | |
96 | 164 |
97 /** | 165 /** |
98 * Creates a class for executing several asynchronous closures in a group in | 166 * Creates a class for executing several asynchronous closures in a group in |
99 * a dependency order. | 167 * a dependency order. |
100 * | 168 * |
101 * @constructor | 169 * @constructor |
102 */ | 170 */ |
103 AsyncUtil.Group = function() { | 171 AsyncUtil.Group = function() { |
104 this.addedTasks_ = {}; | 172 this.addedTasks_ = {}; |
105 this.pendingTasks_ = {}; | 173 this.pendingTasks_ = {}; |
(...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
253 /** | 321 /** |
254 * Cancels all scheduled runs (if any). | 322 * Cancels all scheduled runs (if any). |
255 * @private | 323 * @private |
256 */ | 324 */ |
257 AsyncUtil.Aggregation.prototype.cancelScheduledRuns_ = function() { | 325 AsyncUtil.Aggregation.prototype.cancelScheduledRuns_ = function() { |
258 if (this.scheduledRunsTimer_) { | 326 if (this.scheduledRunsTimer_) { |
259 clearTimeout(this.scheduledRunsTimer_); | 327 clearTimeout(this.scheduledRunsTimer_); |
260 this.scheduledRunsTimer_ = null; | 328 this.scheduledRunsTimer_ = null; |
261 } | 329 } |
262 }; | 330 }; |
OLD | NEW |