diff --git a/demos/worker.html b/demos/worker.html index 8b69b7d..c8eec8a 100644 --- a/demos/worker.html +++ b/demos/worker.html @@ -1,82 +1,38 @@ -Worker -
-

Canvas is running whilst an prime number finder runs in a worker

-

Prime found: 0

-
-
- + + + Worker + + + +

Web Worker Demo

+

Works in Chrome, Safari, and Firefox. Web worker portion works in Opera.

+

Use arrow keys to change the direction of the animated square. The square is animated with requestAnimationFrame.

+

Click the button below to start or stop the worker.

+
+

Messages from Worker:

+
+
+ + + diff --git a/js/cruncher.js b/js/cruncher.js deleted file mode 100644 index 96ec29a..0000000 --- a/js/cruncher.js +++ /dev/null @@ -1,24 +0,0 @@ -var running = false; - -onmessage = function (event) { - // doesn't matter what the message is, just toggle the worker - if (running == false) { - running = true; - run(); - } else { - running = false; - } -}; - -function run() { - var n = 1; - search: while (running) { - n += 1; - for (var i = 2; i <= Math.sqrt(n); i += 1) - if (n % i == 0) - continue search; - // found a prime! - postMessage(n); - } -} - diff --git a/js/worker-cruncher.js b/js/worker-cruncher.js new file mode 100644 index 0000000..82bd24c --- /dev/null +++ b/js/worker-cruncher.js @@ -0,0 +1,68 @@ +/*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, maxerr: 50, browser: true */ +/*global postMessage, addEventListener */ + +(function () { + "use strict"; + + var WHEN_TO_STOP = 10000000; + var COMPUTE_BLOCK_SIZE = 1000000; + + var running = false; + var count = 0; + + // We have to compute in blocks of ~1 second of computation in order to make sure + // that we read our message queue occasionally. Worker threads are not preemptive + // (like all JS), so if we don't pause computation to read the message queue, we'll + // be unresponsive to user requests. + function compute(start) { + var n = start; + var i, hasDivisor; + + if (!running) { // got a message to stop before this call to compute + postMessage("Stopped!"); + } else { + while (n < start + COMPUTE_BLOCK_SIZE) { + hasDivisor = false; + for (i = 2; i <= Math.sqrt(n); i += 1) { + if (n % i === 0) { + hasDivisor = true; + break; + } + } + if (!hasDivisor) { + // found a prime! + count++; + } + n += 1; + } + + if (n < WHEN_TO_STOP) { + // allow for event loop to actually forward messages to the worker + setTimeout(function () { compute(n); }, 1); + } else { + // we reached the end + running = false; + postMessage("Done!"); + } + } + + // Finally, always report how many primes we've found so far + postMessage("Found " + count + " primes between 2 and " + (n - 1)); + + } + + addEventListener('message', function (event) { + // doesn't matter what the message is, just toggle the worker + if (running === false) { + postMessage("Starting..."); + count = 0; + running = true; + compute(1); + } else { + postMessage("Stopping..."); + running = false; + } + }); + + +}()); \ No newline at end of file diff --git a/js/worker-main.js b/js/worker-main.js new file mode 100644 index 0000000..5077b18 --- /dev/null +++ b/js/worker-main.js @@ -0,0 +1,92 @@ +/*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, maxerr: 50, browser: true */ +/*global Worker */ + +(function () { + "use strict"; + + var SQUARE_SIZE = 75; + var MOVEMENT_STEP = 3; + + var requestAnimationFrame = window.requestAnimationFrame || window.mozRequestAnimationFrame || + window.webkitRequestAnimationFrame || window.msRequestAnimationFrame; + + + // Set up the worker + var running = false; + var statusDiv = document.getElementById('status'); + var button = document.getElementById('toggleWorker'); + var worker = new Worker('../js/worker-cruncher.js'); // path is relative to the main HTML file + worker.addEventListener('message', function (event) { + var currentStatus = statusDiv.innerHTML; + statusDiv.innerHTML = "

" + event.data + "

" + currentStatus; + if (event.data === "Done!") { + running = false; + button.value = "start worker"; + } + }); + + button.onclick = function () { + running = !running; + if (running) { + statusDiv.innerHTML = ""; + button.value = "stop worker"; + } else { + button.value = "start worker"; + } + worker.postMessage(''); + + }; + + + // Set up the animated square + var square = document.getElementById('square'); + var direction = 39; // right + + square.style.top = 0; + square.style.left = 20; + square.style.height = SQUARE_SIZE; + square.style.width = SQUARE_SIZE; + + function moveSquare() { + var left = parseInt(square.style.left, 10); + var top = parseInt(square.style.top, 10); + var right = left + SQUARE_SIZE; + var bottom = top + SQUARE_SIZE; + + switch (direction) { + case 37: // left + if (left > 0) { + square.style.left = left - MOVEMENT_STEP; + } + break; + case 38: // up + if (top > 0) { + square.style.top = top - MOVEMENT_STEP; + } + break; + case 39: //right + if (right < document.documentElement.clientWidth) { + square.style.left = left + MOVEMENT_STEP; + } + break; + case 40: // down + if (bottom < document.documentElement.clientHeight) { + square.style.top = top + MOVEMENT_STEP; + } + break; + default: + break; + } + requestAnimationFrame(moveSquare); + } + + window.onkeydown = function (event) { + if (event.keyCode >= 37 && event.keyCode <= 40) { // is an arrow key + direction = event.keyCode; + } + }; + + // start the square animating + requestAnimationFrame(moveSquare); + +}()); \ No newline at end of file diff --git a/js/worker.js b/js/worker.js deleted file mode 100644 index 6e49142..0000000 --- a/js/worker.js +++ /dev/null @@ -1,23 +0,0 @@ -var running = false; -var ctr = 0; - -function log(s) { - postMessage('log:' + s); -} - -onmessage = function (event) { - // doesn't matter what the message is, just toggle the worker - if (running == false) { - running = true; - run(); - } else { - running = false; - } -}; - -function run() { - while (running) { - postMessage(ctr); - ctr++; - } -}