OLD | NEW |
1 <!DOCTYPE html> | 1 <!DOCTYPE html> |
2 <!-- | 2 <!-- |
3 Copyright (c) 2013 The Chromium Authors. All rights reserved. | 3 Copyright (c) 2013 The Chromium Authors. All rights reserved. |
4 Use of this source code is governed by a BSD-style license that can be | 4 Use of this source code is governed by a BSD-style license that can be |
5 found in the LICENSE file. | 5 found in the LICENSE file. |
6 --> | 6 --> |
7 <link rel="import" href="/tracing/base/raf.html"> | 7 <link rel="import" href="/tracing/base/raf.html"> |
8 <link rel="import" href="/tracing/base/timing.html"> | 8 <link rel="import" href="/tracing/base/timing.html"> |
9 | 9 |
10 <script> | 10 <script> |
(...skipping 22 matching lines...) Expand all Loading... |
33 * taskA.after(function(taskA) { | 33 * taskA.after(function(taskA) { |
34 * pieces.forEach(function(piece) { | 34 * pieces.forEach(function(piece) { |
35 * taskA.subTask(function(taskB) { piece.process(); }, this); | 35 * taskA.subTask(function(taskB) { piece.process(); }, this); |
36 * }); | 36 * }); |
37 * }); | 37 * }); |
38 * | 38 * |
39 * @constructor | 39 * @constructor |
40 */ | 40 */ |
41 function Task(runCb, thisArg) { | 41 function Task(runCb, thisArg) { |
42 if (runCb !== undefined && thisArg === undefined && | 42 if (runCb !== undefined && thisArg === undefined && |
43 runCb.prototype !== undefined) | 43 runCb.prototype !== undefined) { |
44 throw new Error('Almost certainly you meant to pass a bound callback ' + | 44 throw new Error('Almost certainly you meant to pass a bound callback ' + |
45 'or thisArg.'); | 45 'or thisArg.'); |
| 46 } |
46 this.runCb_ = runCb; | 47 this.runCb_ = runCb; |
47 this.thisArg_ = thisArg; | 48 this.thisArg_ = thisArg; |
48 this.afterTask_ = undefined; | 49 this.afterTask_ = undefined; |
49 this.subTasks_ = []; | 50 this.subTasks_ = []; |
50 this.updatesUi_ = false; | 51 this.updatesUi_ = false; |
51 } | 52 } |
52 | 53 |
53 Task.prototype = { | 54 Task.prototype = { |
54 get name() { | 55 get name() { |
55 return this.runCb_.name; | 56 return this.runCb_.name; |
56 }, | 57 }, |
57 | 58 |
58 /** Sets a hint for whether or not this task updates the UI. */ | 59 /** Sets a hint for whether or not this task updates the UI. */ |
59 set updatesUi(value) { | 60 set updatesUi(value) { |
60 this.updatesUi_ = value; | 61 this.updatesUi_ = value; |
61 }, | 62 }, |
62 | 63 |
63 /* | 64 /* |
64 * See constructor documentation on semantics of subtasks. | 65 * See constructor documentation on semantics of subtasks. |
65 */ | 66 */ |
66 subTask: function(cb, thisArg) { | 67 subTask: function(cb, thisArg) { |
67 if (cb instanceof Task) | 68 if (cb instanceof Task) { |
68 this.subTasks_.push(cb); | 69 this.subTasks_.push(cb); |
69 else | 70 } else { |
70 this.subTasks_.push(new Task(cb, thisArg)); | 71 this.subTasks_.push(new Task(cb, thisArg)); |
| 72 } |
71 return this.subTasks_[this.subTasks_.length - 1]; | 73 return this.subTasks_[this.subTasks_.length - 1]; |
72 }, | 74 }, |
73 | 75 |
74 /** | 76 /** |
75 * Runs the current task and returns the task that should be executed next. | 77 * Runs the current task and returns the task that should be executed next. |
76 */ | 78 */ |
77 run: function() { | 79 run: function() { |
78 if (this.runCb_ !== undefined) | 80 if (this.runCb_ !== undefined) this.runCb_.call(this.thisArg_, this); |
79 this.runCb_.call(this.thisArg_, this); | |
80 var subTasks = this.subTasks_; | 81 var subTasks = this.subTasks_; |
81 this.subTasks_ = undefined; // Prevent more subTasks from being posted. | 82 this.subTasks_ = undefined; // Prevent more subTasks from being posted. |
82 | 83 |
83 if (!subTasks.length) | 84 if (!subTasks.length) return this.afterTask_; |
84 return this.afterTask_; | |
85 | 85 |
86 // If there are subtasks, then we want to execute all the subtasks and | 86 // If there are subtasks, then we want to execute all the subtasks and |
87 // then this task's afterTask. To make this happen, we update the | 87 // then this task's afterTask. To make this happen, we update the |
88 // afterTask of all the subtasks so the point upward to each other, e.g. | 88 // afterTask of all the subtasks so the point upward to each other, e.g. |
89 // subTask[0].afterTask to subTask[1] and so on. Then, the last subTask's | 89 // subTask[0].afterTask to subTask[1] and so on. Then, the last subTask's |
90 // afterTask points at this task's afterTask. | 90 // afterTask points at this task's afterTask. |
91 for (var i = 1; i < subTasks.length; i++) | 91 for (var i = 1; i < subTasks.length; i++) { |
92 subTasks[i - 1].afterTask_ = subTasks[i]; | 92 subTasks[i - 1].afterTask_ = subTasks[i]; |
| 93 } |
93 subTasks[subTasks.length - 1].afterTask_ = this.afterTask_; | 94 subTasks[subTasks.length - 1].afterTask_ = this.afterTask_; |
94 return subTasks[0]; | 95 return subTasks[0]; |
95 }, | 96 }, |
96 | 97 |
97 /* | 98 /* |
98 * See constructor documentation on semantics of after tasks. | 99 * See constructor documentation on semantics of after tasks. |
99 */ | 100 */ |
100 after: function(cb, thisArg) { | 101 after: function(cb, thisArg) { |
101 if (this.afterTask_) | 102 if (this.afterTask_) { |
102 throw new Error('Has an after task already'); | 103 throw new Error('Has an after task already'); |
103 if (cb instanceof Task) | 104 } |
| 105 if (cb instanceof Task) { |
104 this.afterTask_ = cb; | 106 this.afterTask_ = cb; |
105 else | 107 } else { |
106 this.afterTask_ = new Task(cb, thisArg); | 108 this.afterTask_ = new Task(cb, thisArg); |
| 109 } |
107 return this.afterTask_; | 110 return this.afterTask_; |
108 }, | 111 }, |
109 | 112 |
110 /* | 113 /* |
111 * See constructor documentation on semantics of after tasks. | 114 * See constructor documentation on semantics of after tasks. |
112 * Note: timedAfter doesn't work when a task throws an exception. | 115 * Note: timedAfter doesn't work when a task throws an exception. |
113 * This is because task system doesn't support catching currently. | 116 * This is because task system doesn't support catching currently. |
114 * At the time of writing, this is considered to be an acceptable tradeoff. | 117 * At the time of writing, this is considered to be an acceptable tradeoff. |
115 */ | 118 */ |
116 timedAfter: function(groupName, cb, thisArg, opt_args) { | 119 timedAfter: function(groupName, cb, thisArg, opt_args) { |
117 if (cb.name === '') | 120 if (cb.name === '') { |
118 throw new Error('Anonymous Task is not allowed'); | 121 throw new Error('Anonymous Task is not allowed'); |
| 122 } |
119 return this.namedTimedAfter(groupName, cb.name, cb, thisArg, opt_args); | 123 return this.namedTimedAfter(groupName, cb.name, cb, thisArg, opt_args); |
120 }, | 124 }, |
121 | 125 |
122 /* | 126 /* |
123 * See constructor documentation on semantics of after tasks. | 127 * See constructor documentation on semantics of after tasks. |
124 * Note: namedTimedAfter doesn't work when a task throws an exception. | 128 * Note: namedTimedAfter doesn't work when a task throws an exception. |
125 * This is because task system doesn't support catching currently. | 129 * This is because task system doesn't support catching currently. |
126 * At the time of writing, this is considered to be an acceptable tradeoff. | 130 * At the time of writing, this is considered to be an acceptable tradeoff. |
127 */ | 131 */ |
128 namedTimedAfter: function(groupName, name, cb, thisArg, opt_args) { | 132 namedTimedAfter: function(groupName, name, cb, thisArg, opt_args) { |
129 if (this.afterTask_) | 133 if (this.afterTask_) { |
130 throw new Error('Has an after task already'); | 134 throw new Error('Has an after task already'); |
| 135 } |
131 var realTask; | 136 var realTask; |
132 if (cb instanceof Task) | 137 if (cb instanceof Task) { |
133 realTask = cb; | 138 realTask = cb; |
134 else | 139 } else { |
135 realTask = new Task(cb, thisArg); | 140 realTask = new Task(cb, thisArg); |
| 141 } |
136 this.afterTask_ = new Task(function(task) { | 142 this.afterTask_ = new Task(function(task) { |
137 var markedTask = Timing.mark(groupName, name, opt_args); | 143 var markedTask = Timing.mark(groupName, name, opt_args); |
138 task.subTask(realTask, thisArg); | 144 task.subTask(realTask, thisArg); |
139 task.subTask(function() { | 145 task.subTask(function() { |
140 markedTask.end(); | 146 markedTask.end(); |
141 }, thisArg); | 147 }, thisArg); |
142 }, thisArg); | 148 }, thisArg); |
143 return this.afterTask_; | 149 return this.afterTask_; |
144 }, | 150 }, |
145 | 151 |
146 /* | 152 /* |
147 * Adds a task after the chain of tasks. | 153 * Adds a task after the chain of tasks. |
148 */ | 154 */ |
149 enqueue: function(cb, thisArg) { | 155 enqueue: function(cb, thisArg) { |
150 var lastTask = this; | 156 var lastTask = this; |
151 while (lastTask.afterTask_) | 157 while (lastTask.afterTask_) { |
152 lastTask = lastTask.afterTask_; | 158 lastTask = lastTask.afterTask_; |
| 159 } |
153 return lastTask.after(cb, thisArg); | 160 return lastTask.after(cb, thisArg); |
154 } | 161 } |
155 }; | 162 }; |
156 | 163 |
157 Task.RunSynchronously = function(task) { | 164 Task.RunSynchronously = function(task) { |
158 var curTask = task; | 165 var curTask = task; |
159 while (curTask) | 166 while (curTask) { |
160 curTask = curTask.run(); | 167 curTask = curTask.run(); |
| 168 } |
161 }; | 169 }; |
162 | 170 |
163 /** | 171 /** |
164 * Runs a task using raf.requestIdleCallback, returning | 172 * Runs a task using raf.requestIdleCallback, returning |
165 * a promise for its completion. | 173 * a promise for its completion. |
166 */ | 174 */ |
167 Task.RunWhenIdle = function(task) { | 175 Task.RunWhenIdle = function(task) { |
168 return new Promise(function(resolve, reject) { | 176 return new Promise(function(resolve, reject) { |
169 var curTask = task; | 177 var curTask = task; |
170 function runAnother() { | 178 function runAnother() { |
(...skipping 17 matching lines...) Expand all Loading... |
188 } | 196 } |
189 tr.b.requestIdleCallback(runAnother); | 197 tr.b.requestIdleCallback(runAnother); |
190 }); | 198 }); |
191 }; | 199 }; |
192 | 200 |
193 return { | 201 return { |
194 Task, | 202 Task, |
195 }; | 203 }; |
196 }); | 204 }); |
197 </script> | 205 </script> |
OLD | NEW |