Created
March 31, 2010 23:04
-
-
Save kixxauth/351058 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* A simple parallel program in JavaScript for the Rhino JavaScript engine. | |
*/ | |
// Set up the globals. | |
// | |
// While JavaScript allows all values and references in the global scope to be | |
// dynamic, only objects (JavaScript arrays and object natives) are mutable "in | |
// place". It is up to the programmer to keep the global namespace clear in a | |
// multithreaded environment. Because this is a simple program, I didn't do | |
// that here. | |
// In case we're running in a CommonJS complient environment we attempt to | |
// import the `system` module. If not, we still need the `arguments` global | |
// given to us by Rhino to get the command line arguments. | |
var sys = typeof require === "function" ? require("system") : {args: arguments}, | |
// Performance mode; a boolean flag. | |
// If true it silences the output (no print statements). | |
PERF, | |
// The number of random numbers for the main thread to generate. | |
RND_NUMS, | |
// The number of threads to run. | |
NUM_THREADS, | |
// An indexed list of threads for each stack. | |
// This is the only globally shared, mutable data structure. Rhino provides | |
// an atomic guarantee for all JavaScript objects shared between threads. | |
stacks = [], | |
// The start time (UTC timestamp to millisecond resolution. | |
start; | |
// Create a function that will become the last thread. | |
// Param n is the thread id number. | |
function last_thread(n) { | |
return function () { | |
function check() { | |
var fin; | |
// The index for the stack that belongs to | |
// this thread n is found by doing n - 1. | |
while (stacks[n -1].length) { | |
// Shift the next number off the stack. | |
fin = stacks[n -1].shift(); | |
// Add the thread id if it is NOT the last generated number. | |
if (fin !== -1) { | |
fin = fin + n; | |
} | |
// If we're not running in perfomance mode, | |
// and this is NOT the last generated number, | |
// print the result. | |
if (!PERF && fin !== -1) { | |
print(" = "+ fin); | |
} | |
} | |
// This thread has emptied its stack. | |
// However, if the last generated number has not been recieved yet, | |
// we check the stack again after a small delay to allow more | |
// numbers to be genterated. | |
if (fin !== -1) { | |
// The more threads we have, the more time we need. | |
java.lang.Thread.sleep(NUM_THREADS); | |
check(); | |
} | |
// Print performance results at the end of the program. | |
else { | |
print(" # performance: "+ ((new Date().getTime()) - start) +" ms"); | |
} | |
} | |
check(); | |
}; | |
} | |
// Create a function to spawn a generic thread. | |
// Param n is the thread id number. | |
function generic_thread(n) { | |
return function () { | |
function check() { | |
var fin; | |
// The index for the stack that belongs to | |
// this thread n is found by doing n - 1. | |
while (stacks[n -1].length) { | |
// Shift the next number off the stack. | |
fin = stacks[n -1].shift(); | |
// Add the thread id if it is NOT the last generated number. | |
if (fin !== -1) { | |
fin = fin + n; | |
} | |
// Push the new number onto the next thread's stack. | |
stacks[n].push(fin); | |
} | |
// This thread has emptied its stack. | |
// However, if the last generated number has not been recieved yet, | |
// we check the stack again after a small delay to allow more | |
// numbers to be genterated. | |
if (fin !== -1) { | |
// The more threads we have, the more time we need. | |
java.lang.Thread.sleep(NUM_THREADS); | |
check(); | |
} | |
} | |
check(); | |
} | |
} | |
function main() { | |
var n, i, y; | |
// The first cl arg should be the number of threads to run. | |
// If not given, the default is 1. | |
NUM_THREADS = sys.args[1] !== undefined ? +sys.args[1] : 1; | |
// The second cl arg should be the number of random numbers to generate. | |
// If not given, the default is 10000. | |
RND_NUMS = sys.args[2] !== undefined ? +sys.args[2] : 10000; | |
// The third cl arg will set the boolean perfomance mode. | |
// If not given, the default is false. | |
PERF = (sys.args[3] === "false") ? false : (sys.args[3] || false); | |
start = new Date().getTime(); | |
for(n = 1; n <= NUM_THREADS; n += 1) { | |
// Create a stack for the thread. | |
stacks.push([]); | |
// If this is the last thread to generate, spawn a last_thread function, | |
// else return a generic_thread function. | |
spawn((n === NUM_THREADS) ? last_thread(n) : generic_thread(n)); | |
} | |
// Generate random numbers > 1 and < 20; | |
for (i = 0; i < RND_NUMS; i++) { | |
y = 2+ (Math.random() *19) | 0; | |
if (!PERF) { | |
// If not in performance mode, print the yeilded number. | |
print("yield: "+ y); | |
} | |
// Push the number onto the first stack. | |
stacks[0].push(y); | |
} | |
// Push an out of range number to signal the end of the generation. | |
stacks[0].push(-1); | |
} | |
// Gitterdone. | |
main(); | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment