1 if (rio.Thread) { rio.Thread.disable(); } 2 3 rio.Thread = { 4 jobs: [], 5 groups: {}, 6 frequency: 100, 7 lastPulse: new Date(), 8 pulse: function() { 9 if (this.jobs.length == 0) { 10 this.lastPulse = new Date(); 11 return; 12 } 13 14 var start = new Date(); 15 if (start - this.lastPulse < 50) { 16 // rio.log("Thread.skipping_beat - " + (start - this.lastPulse)); 17 return; 18 } 19 20 try { 21 var count = this.frequency; 22 23 var job = this.jobs.shift(); 24 while (job) { 25 job(); 26 if (count--) { job = this.jobs.shift(); } else { job = false; } 27 } 28 } catch(e) { 29 rio.warn("thread failed"); 30 } finally { 31 this.lastPulse = new Date(); 32 var delay = this.lastPulse - start; 33 34 if (this.jobs.length > 0) { 35 if (delay > 100) { 36 this.frequency /= 2; 37 // rio.log("Thread.frequency changed to: " + this.frequency); 38 } else if (delay < 30) { 39 this.frequency = (this.frequency * 1.5).ceil(); 40 // rio.log("Thread.frequency changed to: " + this.frequency); 41 } 42 // rio.log("Thread.delay - " + delay); 43 } 44 } 45 }, 46 47 fork: function(fcn, options) { 48 var groupName = (options || {}).group; 49 if (groupName) { 50 var group = this.groups[groupName]; 51 if (!group) { 52 group = { 53 suspended: options.suspended, 54 jobs: [] 55 }; 56 this.groups[groupName] = group; 57 } else { 58 if (options.suspended != undefined) { 59 if (group.suspended && !options.suspended) { 60 this.resume(groupName); 61 } else if (!group.suspended && options.suspended) { 62 group.suspended = true; 63 } 64 } 65 } 66 67 68 if (!group.suspended) { 69 // rio.log("Thread.fork job for group: " + groupName); 70 this.jobs.push(fcn); 71 } else { 72 group.jobs.push(fcn); 73 } 74 75 } else { 76 this.jobs.push(fcn); 77 } 78 }, 79 80 resume: function(groupName, options) { 81 try { 82 (function() { 83 var group = this.groups[groupName]; 84 for (var i=0, length=group.jobs.length; i<length; i++) { 85 this.jobs.push(group.jobs[i]); 86 } 87 group.jobs.clear(); 88 group.suspended = false; 89 }.bind(this)).delay((options || {}).delay || 0); 90 } catch(e) { 91 rio.warn("Thread.resume failed to resume group: " + groupName); 92 throw(e); 93 } 94 }, 95 96 suspend: function(groupName) { 97 var group = this.groups[groupName]; 98 if (!group) { 99 group = { 100 jobs: [] 101 }; 102 this.groups[groupName] = group; 103 } 104 group.suspended = true; 105 }, 106 107 enable: function() { 108 if (this.pulseIntervalId) { return; } 109 this.pulseIntervalId = setInterval(rio.Thread.pulse.bind(rio.Thread), 100); 110 }, 111 112 disable: function() { 113 if (this.pulseIntervalId) { 114 clearInterval(this.pulseIntervalId); 115 } 116 } 117 }; 118 119 rio.Thread.enable(); 120 121