Upgrade to ExtJS 3.1.0 - Released 12/16/2009
[extjs.git] / src / util / core / TaskMgr.js
1 /*!
2  * Ext JS Library 3.1.0
3  * Copyright(c) 2006-2009 Ext JS, LLC
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  * Also see {@link Ext.util.DelayedTask}. 
34  * 
35  * @constructor
36  * @param {Number} interval (optional) The minimum precision in milliseconds supported by this TaskRunner instance
37  * (defaults to 10)
38  */
39 Ext.util.TaskRunner = function(interval){
40     interval = interval || 10;
41     var tasks = [], 
42         removeQueue = [],
43         id = 0,
44         running = false,
45
46         // private
47         stopThread = function(){
48                 running = false;
49                 clearInterval(id);
50                 id = 0;
51             },
52
53         // private
54         startThread = function(){
55                 if(!running){
56                     running = true;
57                     id = setInterval(runTasks, interval);
58                 }
59             },
60
61         // private
62         removeTask = function(t){
63                 removeQueue.push(t);
64                 if(t.onStop){
65                     t.onStop.apply(t.scope || t);
66                 }
67             },
68             
69         // private
70         runTasks = function(){
71                 var rqLen = removeQueue.length,
72                         now = new Date().getTime();                                             
73             
74                 if(rqLen > 0){
75                     for(var i = 0; i < rqLen; i++){
76                         tasks.remove(removeQueue[i]);
77                     }
78                     removeQueue = [];
79                     if(tasks.length < 1){
80                         stopThread();
81                         return;
82                     }
83                 }               
84                 for(var i = 0, t, itime, rt, len = tasks.length; i < len; ++i){
85                     t = tasks[i];
86                     itime = now - t.taskRunTime;
87                     if(t.interval <= itime){
88                         rt = t.run.apply(t.scope || t, t.args || [++t.taskRunCount]);
89                         t.taskRunTime = now;
90                         if(rt === false || t.taskRunCount === t.repeat){
91                             removeTask(t);
92                             return;
93                         }
94                     }
95                     if(t.duration && t.duration <= (now - t.taskStartTime)){
96                         removeTask(t);
97                     }
98                 }
99             };
100
101     /**
102      * Starts a new task.
103      * @method start
104      * @param {Object} task A config object that supports the following properties:<ul>
105      * <li><code>run</code> : Function<div class="sub-desc">The function to execute each time the task is run. The
106      * function will be called at each interval and passed the <code>args</code> argument if specified.  If a
107      * particular scope is required, be sure to specify it using the <code>scope</code> argument.</div></li>
108      * <li><code>interval</code> : Number<div class="sub-desc">The frequency in milliseconds with which the task
109      * should be executed.</div></li>
110      * <li><code>args</code> : Array<div class="sub-desc">(optional) An array of arguments to be passed to the function
111      * specified by <code>run</code>.</div></li>
112      * <li><code>scope</code> : Object<div class="sub-desc">(optional) The scope (<tt>this</tt> reference) in which to execute the
113      * <code>run</code> function. Defaults to the task config object.</div></li>
114      * <li><code>duration</code> : Number<div class="sub-desc">(optional) The length of time in milliseconds to execute
115      * the task before stopping automatically (defaults to indefinite).</div></li>
116      * <li><code>repeat</code> : Number<div class="sub-desc">(optional) The number of times to execute the task before
117      * stopping automatically (defaults to indefinite).</div></li>
118      * </ul>
119      * @return {Object} The task
120      */
121     this.start = function(task){
122         tasks.push(task);
123         task.taskStartTime = new Date().getTime();
124         task.taskRunTime = 0;
125         task.taskRunCount = 0;
126         startThread();
127         return task;
128     };
129
130     /**
131      * Stops an existing running task.
132      * @method stop
133      * @param {Object} task The task to stop
134      * @return {Object} The task
135      */
136     this.stop = function(task){
137         removeTask(task);
138         return task;
139     };
140
141     /**
142      * Stops all tasks that are currently running.
143      * @method stopAll
144      */
145     this.stopAll = function(){
146         stopThread();
147         for(var i = 0, len = tasks.length; i < len; i++){
148             if(tasks[i].onStop){
149                 tasks[i].onStop();
150             }
151         }
152         tasks = [];
153         removeQueue = [];
154     };
155 };
156
157 /**
158  * @class Ext.TaskMgr
159  * @extends Ext.util.TaskRunner
160  * A static {@link Ext.util.TaskRunner} instance that can be used to start and stop arbitrary tasks.  See
161  * {@link Ext.util.TaskRunner} for supported methods and task config properties.
162  * <pre><code>
163 // Start a simple clock task that updates a div once per second
164 var task = {
165     run: function(){
166         Ext.fly('clock').update(new Date().format('g:i:s A'));
167     },
168     interval: 1000 //1 second
169 }
170 Ext.TaskMgr.start(task);
171 </code></pre>
172  * @singleton
173  */
174 Ext.TaskMgr = new Ext.util.TaskRunner();