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 | }); |
---|