Upgrade to ExtJS 4.0.7 - Released 10/19/2011
[extjs.git] / src / core / src / util / TaskManager.js
1 /*
2
3 This file is part of Ext JS 4
4
5 Copyright (c) 2011 Sencha Inc
6
7 Contact:  http://www.sencha.com/contact
8
9 GNU General Public License Usage
10 This file may be used under the terms of the GNU General Public License version 3.0 as published by the Free Software Foundation and appearing in the file LICENSE included in the packaging of this file.  Please review the following information to ensure the GNU General Public License version 3.0 requirements will be met: http://www.gnu.org/copyleft/gpl.html.
11
12 If you are unsure which license is appropriate for your use, please contact the sales department at http://www.sencha.com/contact.
13
14 */
15 /**
16  * @class Ext.util.TaskRunner
17  * Provides the ability to execute one or more arbitrary tasks in a multithreaded
18  * manner.  Generally, you can use the singleton {@link Ext.TaskManager} instead, but
19  * if needed, you can create separate instances of TaskRunner.  Any number of
20  * separate tasks can be started at any time and will run independently of each
21  * other. Example usage:
22  * <pre><code>
23 // Start a simple clock task that updates a div once per second
24 var updateClock = function(){
25     Ext.fly('clock').update(new Date().format('g:i:s A'));
26
27 var task = {
28     run: updateClock,
29     interval: 1000 //1 second
30 }
31 var runner = new Ext.util.TaskRunner();
32 runner.start(task);
33
34 // equivalent using TaskManager
35 Ext.TaskManager.start({
36     run: updateClock,
37     interval: 1000
38 });
39
40  * </code></pre>
41  * <p>See the {@link #start} method for details about how to configure a task object.</p>
42  * Also see {@link Ext.util.DelayedTask}. 
43  * 
44  * @constructor
45  * @param {Number} [interval=10] The minimum precision in milliseconds supported by this TaskRunner instance
46  */
47 Ext.ns('Ext.util');
48
49 Ext.util.TaskRunner = function(interval) {
50     interval = interval || 10;
51     var tasks = [],
52     removeQueue = [],
53     id = 0,
54     running = false,
55
56     // private
57     stopThread = function() {
58         running = false;
59         clearInterval(id);
60         id = 0;
61     },
62
63     // private
64     startThread = function() {
65         if (!running) {
66             running = true;
67             id = setInterval(runTasks, interval);
68         }
69     },
70
71     // private
72     removeTask = function(t) {
73         removeQueue.push(t);
74         if (t.onStop) {
75             t.onStop.apply(t.scope || t);
76         }
77     },
78
79     // private
80     runTasks = function() {
81         var rqLen = removeQueue.length,
82             now = new Date().getTime(),
83             i;
84
85         if (rqLen > 0) {
86             for (i = 0; i < rqLen; i++) {
87                 Ext.Array.remove(tasks, removeQueue[i]);
88             }
89             removeQueue = [];
90             if (tasks.length < 1) {
91                 stopThread();
92                 return;
93             }
94         }
95         i = 0;
96         var t,
97             itime,
98             rt,
99             len = tasks.length;
100         for (; i < len; ++i) {
101             t = tasks[i];
102             itime = now - t.taskRunTime;
103             if (t.interval <= itime) {
104                 rt = t.run.apply(t.scope || t, t.args || [++t.taskRunCount]);
105                 t.taskRunTime = now;
106                 if (rt === false || t.taskRunCount === t.repeat) {
107                     removeTask(t);
108                     return;
109                 }
110             }
111             if (t.duration && t.duration <= (now - t.taskStartTime)) {
112                 removeTask(t);
113             }
114         }
115     };
116
117     /**
118      * Starts a new task.
119      * @method start
120      * @param {Object} task <p>A config object that supports the following properties:<ul>
121      * <li><code>run</code> : Function<div class="sub-desc"><p>The function to execute each time the task is invoked. The
122      * function will be called at each interval and passed the <code>args</code> argument if specified, and the
123      * current invocation count if not.</p>
124      * <p>If a particular scope (<code>this</code> reference) is required, be sure to specify it using the <code>scope</code> argument.</p>
125      * <p>Return <code>false</code> from this function to terminate the task.</p></div></li>
126      * <li><code>interval</code> : Number<div class="sub-desc">The frequency in milliseconds with which the task
127      * should be invoked.</div></li>
128      * <li><code>args</code> : Array<div class="sub-desc">(optional) An array of arguments to be passed to the function
129      * specified by <code>run</code>. If not specified, the current invocation count is passed.</div></li>
130      * <li><code>scope</code> : Object<div class="sub-desc">(optional) The scope (<tt>this</tt> reference) in which to execute the
131      * <code>run</code> function. Defaults to the task config object.</div></li>
132      * <li><code>duration</code> : Number<div class="sub-desc">(optional) The length of time in milliseconds to invoke
133      * the task before stopping automatically (defaults to indefinite).</div></li>
134      * <li><code>repeat</code> : Number<div class="sub-desc">(optional) The number of times to invoke the task before
135      * stopping automatically (defaults to indefinite).</div></li>
136      * </ul></p>
137      * <p>Before each invocation, Ext injects the property <code>taskRunCount</code> into the task object so
138      * that calculations based on the repeat count can be performed.</p>
139      * @return {Object} The task
140      */
141     this.start = function(task) {
142         tasks.push(task);
143         task.taskStartTime = new Date().getTime();
144         task.taskRunTime = 0;
145         task.taskRunCount = 0;
146         startThread();
147         return task;
148     };
149
150     /**
151      * Stops an existing running task.
152      * @method stop
153      * @param {Object} task The task to stop
154      * @return {Object} The task
155      */
156     this.stop = function(task) {
157         removeTask(task);
158         return task;
159     };
160
161     /**
162      * Stops all tasks that are currently running.
163      * @method stopAll
164      */
165     this.stopAll = function() {
166         stopThread();
167         for (var i = 0, len = tasks.length; i < len; i++) {
168             if (tasks[i].onStop) {
169                 tasks[i].onStop();
170             }
171         }
172         tasks = [];
173         removeQueue = [];
174     };
175 };
176
177 /**
178  * @class Ext.TaskManager
179  * @extends Ext.util.TaskRunner
180  * A static {@link Ext.util.TaskRunner} instance that can be used to start and stop arbitrary tasks.  See
181  * {@link Ext.util.TaskRunner} for supported methods and task config properties.
182  * <pre><code>
183 // Start a simple clock task that updates a div once per second
184 var task = {
185     run: function(){
186         Ext.fly('clock').update(new Date().format('g:i:s A'));
187     },
188     interval: 1000 //1 second
189 }
190 Ext.TaskManager.start(task);
191 </code></pre>
192  * <p>See the {@link #start} method for details about how to configure a task object.</p>
193  * @singleton
194  */
195 Ext.TaskManager = Ext.create('Ext.util.TaskRunner');