- Author:
- David Nickerson <nickerso@users.sourceforge.net>
- Date:
- 2009-07-16 02:00:03+12:00
- Desc:
- the starting point for the HH tutorial example
- Permanent Source URI:
- https://models.fieldml.org/workspace/a1/rawfile/f6a8f90307388eb4b040ee3566b84d88b59247f7/dojo-presentation/js/dojo/dojox/timing/ThreadPool.js
dojo.provide("dojox.timing.ThreadPool");
dojo.require("dojox.timing");
dojo.experimental("dojox.timing.ThreadPool");
// dojox.timing.Timer is included as part of _base
/********************************************************************
This is a port of the original System.Threading.ThreadPool from
the f(m) class library.
Donated to the Dojo toolkit by the author :)
*********************************************************************/
(function(){
var t=dojox.timing;
t.threadStates={
UNSTARTED:"unstarted",
STOPPED:"stopped",
PENDING:"pending",
RUNNING:"running",
SUSPENDED:"suspended",
WAITING:"waiting",
COMPLETE:"complete",
ERROR:"error"
};
// Before rar says a word, we actually *use* these numbers for a purpose :)
t.threadPriorities={
LOWEST:1,
BELOWNORMAL:2,
NORMAL:3,
ABOVENORMAL:4,
HIGHEST:5
};
t.Thread=function(/* Function */fn, /* dojox.timing.threadPriorities? */priority){
var self=this;
this.state=t.threadStates.UNSTARTED;
this.priority=priority||t.threadPriorities.NORMAL;
this.lastError=null;
this.func=fn; // for lookup purposes.
this.invoke=function(){
self.state=t.threadStates.RUNNING;
try{
fn(this);
self.state=t.threadStates.COMPLETE;
}catch(e){
self.lastError=e;
self.state=t.threadStates.ERROR;
}
};
};
// TODO: allow for changing of maxThreads and tick interval
t.ThreadPool=new (function(/* Number */mxthrs, /* Number */intvl){
var self=this;
var maxThreads=mxthrs;
var availableThreads=maxThreads;
var interval=intvl;
var fireInterval=Math.floor((interval/2)/maxThreads);
var queue=[];
var timers=new Array(maxThreads+1);
var timer=new dojox.timing.Timer();
var invoke=function(){
var tracker=timers[0]={};
for(var i=0; i<timers.length; i++){
window.clearTimeout(timers[i]);
var thread=queue.shift();
if(typeof(thread)=="undefined"){ break; }
tracker["thread-"+i]=thread;
timers[i]=window.setTimeout(thread.invoke,(fireInterval*i));
}
availableThreads=maxThreads-(i-1);
};
// public methods
this.getMaxThreads=function(){ return maxThreads; };
this.getAvailableThreads=function(){ return availableThreads; };
this.getTickInterval=function(){ return interval; };
this.queueUserWorkItem=function(/* Function || dojox.timing.Thread */fn){
var item=fn;
if(item instanceof Function){
item=new t.Thread(item);
}
var idx=queue.length;
for(var i=0; i<queue.length; i++){
if(queue[i].priority<item.priority){
idx=i;
break;
}
}
if(idx<queue.length){
queue.splice(idx, 0, item);
} else {
queue.push(item);
}
return true;
};
this.removeQueuedUserWorkItem=function(/* Function || dojox.timing.Thread */item){
if(item instanceof Function){
var idx=-1;
for(var i=0; i<queue.length; i++){
if(queue[i].func==item){
idx=i;
break;
}
}
if(idx>-1){
queue.splice(idx,1);
return true;
}
return false;
}
var idx=-1;
for(var i=0; i<queue.length; i++){
if(queue[i]==item){
idx=i;
break;
}
}
if(idx>-1){
queue.splice(idx,1);
return true;
}
return false;
};
this.start=function(){ timer.start(); };
this.stop=function(){ timer.stop(); };
this.abort=function(){
this.stop();
for(var i=1; i<timers.length; i++){
if(timers[i]){
window.clearTimeout(timers[i]);
}
}
for(var thread in timers[0]){
this.queueUserWorkItem(thread);
}
timers[0]={};
};
this.reset=function(){
this.abort();
queue=[];
};
this.sleep=function(/* Number */nSleep){
timer.stop();
window.setTimeout(timer.start, nSleep);
};
// dedicate the timer to us.
timer.onTick=self.invoke;
})(16, 5000);
})();