ThreadPool.js 3.7 KB

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