Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
/**
* 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
You can’t perform that action at this time.