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