ThreadPool.js 4.1 KB

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