[483] | 1 | define(["./_base"], function(){ |
---|
| 2 | dojo.experimental("dojox.timing.ThreadPool"); |
---|
| 3 | |
---|
| 4 | // dojox.timing.Timer is included as part of _base |
---|
| 5 | /******************************************************************** |
---|
| 6 | This is a port of the original System.Threading.ThreadPool from |
---|
| 7 | the f(m) class library. |
---|
| 8 | |
---|
| 9 | Donated to the Dojo toolkit by the author :) |
---|
| 10 | *********************************************************************/ |
---|
| 11 | var t=dojox.timing; |
---|
| 12 | t.threadStates={ |
---|
| 13 | UNSTARTED:"unstarted", |
---|
| 14 | STOPPED:"stopped", |
---|
| 15 | PENDING:"pending", |
---|
| 16 | RUNNING:"running", |
---|
| 17 | SUSPENDED:"suspended", |
---|
| 18 | WAITING:"waiting", |
---|
| 19 | COMPLETE:"complete", |
---|
| 20 | ERROR:"error" |
---|
| 21 | }; |
---|
| 22 | |
---|
| 23 | // Before rar says a word, we actually *use* these numbers for a purpose :) |
---|
| 24 | t.threadPriorities={ |
---|
| 25 | LOWEST:1, |
---|
| 26 | BELOWNORMAL:2, |
---|
| 27 | NORMAL:3, |
---|
| 28 | ABOVENORMAL:4, |
---|
| 29 | HIGHEST:5 |
---|
| 30 | }; |
---|
| 31 | |
---|
| 32 | t.Thread=function(/* Function */fn, /* dojox.timing.threadPriorities? */priority){ |
---|
| 33 | var self=this; |
---|
| 34 | this.state=t.threadStates.UNSTARTED; |
---|
| 35 | this.priority=priority||t.threadPriorities.NORMAL; |
---|
| 36 | this.lastError=null; |
---|
| 37 | this.func=fn; // for lookup purposes. |
---|
| 38 | this.invoke=function(){ |
---|
| 39 | self.state=t.threadStates.RUNNING; |
---|
| 40 | try{ |
---|
| 41 | fn(this); |
---|
| 42 | self.state=t.threadStates.COMPLETE; |
---|
| 43 | }catch(e){ |
---|
| 44 | self.lastError=e; |
---|
| 45 | self.state=t.threadStates.ERROR; |
---|
| 46 | } |
---|
| 47 | }; |
---|
| 48 | }; |
---|
| 49 | |
---|
| 50 | // TODO: allow for changing of maxThreads and tick interval |
---|
| 51 | t.ThreadPool=new (function(/* Number */mxthrs, /* Number */intvl){ |
---|
| 52 | var self=this; |
---|
| 53 | var maxThreads=mxthrs; |
---|
| 54 | var availableThreads=maxThreads; |
---|
| 55 | var interval=intvl; |
---|
| 56 | var fireInterval=Math.floor((interval/2)/maxThreads); |
---|
| 57 | var queue=[]; |
---|
| 58 | var timers=new Array(maxThreads+1); |
---|
| 59 | var timer=new dojox.timing.Timer(); |
---|
| 60 | var invoke=function(){ |
---|
| 61 | var tracker=timers[0]={}; |
---|
| 62 | for(var i=0; i<timers.length; i++){ |
---|
| 63 | window.clearTimeout(timers[i]); |
---|
| 64 | var thread=queue.shift(); |
---|
| 65 | if(typeof(thread)=="undefined"){ break; } |
---|
| 66 | tracker["thread-"+i]=thread; |
---|
| 67 | timers[i]=window.setTimeout(thread.invoke,(fireInterval*i)); |
---|
| 68 | } |
---|
| 69 | availableThreads=maxThreads-(i-1); |
---|
| 70 | }; |
---|
| 71 | |
---|
| 72 | // public methods |
---|
| 73 | this.getMaxThreads=function(){ return maxThreads; }; |
---|
| 74 | this.getAvailableThreads=function(){ return availableThreads; }; |
---|
| 75 | this.getTickInterval=function(){ return interval; }; |
---|
| 76 | this.queueUserWorkItem=function(/* Function|dojox/timing/Thread */fn){ |
---|
| 77 | var item=fn; |
---|
| 78 | if(item instanceof Function){ |
---|
| 79 | item=new t.Thread(item); |
---|
| 80 | } |
---|
| 81 | var idx=queue.length; |
---|
| 82 | for(var i=0; i<queue.length; i++){ |
---|
| 83 | if(queue[i].priority<item.priority){ |
---|
| 84 | idx=i; |
---|
| 85 | break; |
---|
| 86 | } |
---|
| 87 | } |
---|
| 88 | if(idx<queue.length){ |
---|
| 89 | queue.splice(idx, 0, item); |
---|
| 90 | } else { |
---|
| 91 | queue.push(item); |
---|
| 92 | } |
---|
| 93 | return true; |
---|
| 94 | }; |
---|
| 95 | this.removeQueuedUserWorkItem=function(/* Function|dojox/timing/Thread */item){ |
---|
| 96 | if(item instanceof Function){ |
---|
| 97 | var idx=-1; |
---|
| 98 | for(var i=0; i<queue.length; i++){ |
---|
| 99 | if(queue[i].func==item){ |
---|
| 100 | idx=i; |
---|
| 101 | break; |
---|
| 102 | } |
---|
| 103 | } |
---|
| 104 | if(idx>-1){ |
---|
| 105 | queue.splice(idx,1); |
---|
| 106 | return true; |
---|
| 107 | } |
---|
| 108 | return false; |
---|
| 109 | } |
---|
| 110 | |
---|
| 111 | var idx=-1; |
---|
| 112 | for(var i=0; i<queue.length; i++){ |
---|
| 113 | if(queue[i]==item){ |
---|
| 114 | idx=i; |
---|
| 115 | break; |
---|
| 116 | } |
---|
| 117 | } |
---|
| 118 | if(idx>-1){ |
---|
| 119 | queue.splice(idx,1); |
---|
| 120 | return true; |
---|
| 121 | } |
---|
| 122 | return false; |
---|
| 123 | }; |
---|
| 124 | this.start=function(){ timer.start(); }; |
---|
| 125 | this.stop=function(){ timer.stop(); }; |
---|
| 126 | this.abort=function(){ |
---|
| 127 | this.stop(); |
---|
| 128 | for(var i=1; i<timers.length; i++){ |
---|
| 129 | if(timers[i]){ |
---|
| 130 | window.clearTimeout(timers[i]); |
---|
| 131 | } |
---|
| 132 | } |
---|
| 133 | for(var thread in timers[0]){ |
---|
| 134 | this.queueUserWorkItem(thread); |
---|
| 135 | } |
---|
| 136 | timers[0]={}; |
---|
| 137 | }; |
---|
| 138 | this.reset=function(){ |
---|
| 139 | this.abort(); |
---|
| 140 | queue=[]; |
---|
| 141 | }; |
---|
| 142 | this.sleep=function(/* Number */nSleep){ |
---|
| 143 | timer.stop(); |
---|
| 144 | window.setTimeout(timer.start, nSleep); |
---|
| 145 | }; |
---|
| 146 | |
---|
| 147 | // dedicate the timer to us. |
---|
| 148 | timer.onTick=self.invoke; |
---|
| 149 | })(16, 5000); |
---|
| 150 | return dojox.timing.ThreadPool; |
---|
| 151 | }); |
---|