Upgrade to ExtJS 4.0.2 - Released 06/09/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 (optional) The minimum precision in milliseconds supported by this TaskRunner instance
46  * (defaults to 10)
47  */
48 Ext.ns('Ext.util');
49
50 Ext.util.TaskRunner = function(interval) {
51     interval = interval || 10;
52     var tasks = [],
53     removeQueue = [],
54     id = 0,
55     running = false,
56
57     // private
58     stopThread = function() {
59         running = false;
60         clearInterval(id);
61         id = 0;
62     },
63
64     // private
65     startThread = function() {
66         if (!running) {
67             running = true;
68             id = setInterval(runTasks, interval);
69         }
70     },
71
72     // private
73     removeTask = function(t) {
74         removeQueue.push(t);
75         if (t.onStop) {
76             t.onStop.apply(t.scope || t);
77         }
78     },
79
80     // private
81     runTasks = function() {
82         var rqLen = removeQueue.length,
83             now = new Date().getTime(),
84             i;
85
86         if (rqLen > 0) {
87             for (i = 0; i < rqLen; i++) {
88                 Ext.Array.remove(tasks, removeQueue[i]);
89             }
90             removeQueue = [];
91             if (tasks.length < 1) {
92                 stopThread();
93                 return;
94             }
95         }
96         i = 0;
97         var t,
98             itime,
99             rt,
100             len = tasks.length;
101         for (; i < len; ++i) {
102             t = tasks[i];
103             itime = now - t.taskRunTime;
104             if (t.interval <= itime) {
105                 rt = t.run.apply(t.scope || t, t.args || [++t.taskRunCount]);
106                 t.taskRunTime = now;
107                 if (rt === false || t.taskRunCount === t.repeat) {
108                     removeTask(t);
109                     return;
110                 }
111             }
112             if (t.duration && t.duration <= (now - t.taskStartTime)) {
113                 removeTask(t);
114             }
115         }
116     };
117
118     /**
119      * Starts a new task.
120      * @method start
121      * @param {Object} task <p>A config object that supports the following properties:<ul>
122      * <li><code>run</code> : Function<div class="sub-desc"><p>The function to execute each time the task is invoked. The
123      * function will be called at each interval and passed the <code>args</code> argument if specified, and the
124      * current invocation count if not.</p>
125      * <p>If a particular scope (<code>this</code> reference) is required, be sure to specify it using the <code>scope</code> argument.</p>
126      * <p>Return <code>false</code> from this function to terminate the task.</p></div></li>
127      * <li><code>interval</code> : Number<div class="sub-desc">The frequency in milliseconds with which the task
128      * should be invoked.</div></li>
129      * <li><code>args</code> : Array<div class="sub-desc">(optional) An array of arguments to be passed to the function
130      * specified by <code>run</code>. If not specified, the current invocation count is passed.</div></li>
131      * <li><code>scope</code> : Object<div class="sub-desc">(optional) The scope (<tt>this</tt> reference) in which to execute the
132      * <code>run</code> function. Defaults to the task config object.</div></li>
133      * <li><code>duration</code> : Number<div class="sub-desc">(optional) The length of time in milliseconds to invoke
134      * the task before stopping automatically (defaults to indefinite).</div></li>
135      * <li><code>repeat</code> : Number<div class="sub-desc">(optional) The number of times to invoke the task before
136      * stopping automatically (defaults to indefinite).</div></li>
137      * </ul></p>
138      * <p>Before each invocation, Ext injects the property <code>taskRunCount</code> into the task object so
139      * that calculations based on the repeat count can be performed.</p>
140      * @return {Object} The task
141      */
142     this.start = function(task) {
143         tasks.push(task);
144         task.taskStartTime = new Date().getTime();
145         task.taskRunTime = 0;
146         task.taskRunCount = 0;
147         startThread();
148         return task;
149     };
150
151     /**
152      * Stops an existing running task.
153      * @method stop
154      * @param {Object} task The task to stop
155      * @return {Object} The task
156      */
157     this.stop = function(task) {
158         removeTask(task);
159         return task;
160     };
161
162     /**
163      * Stops all tasks that are currently running.
164      * @method stopAll
165      */
166     this.stopAll = function() {
167         stopThread();
168         for (var i = 0, len = tasks.length; i < len; i++) {
169             if (tasks[i].onStop) {
170                 tasks[i].onStop();
171             }
172         }
173         tasks = [];
174         removeQueue = [];
175     };
176 };
177
178 /**
179  * @class Ext.TaskManager
180  * @extends Ext.util.TaskRunner
181  * A static {@link Ext.util.TaskRunner} instance that can be used to start and stop arbitrary tasks.  See
182  * {@link Ext.util.TaskRunner} for supported methods and task config properties.
183  * <pre><code>
184 // Start a simple clock task that updates a div once per second
185 var task = {
186     run: function(){
187         Ext.fly('clock').update(new Date().format('g:i:s A'));
188     },
189     interval: 1000 //1 second
190 }
191 Ext.TaskManager.start(task);
192 </code></pre>
193  * <p>See the {@link #start} method for details about how to configure a task object.</p>
194  * @singleton
195  */
196 Ext.TaskManager = Ext.create('Ext.util.TaskRunner');