Concurrent computing: Difference between revisions
Line 129: | Line 129: | ||
sleep rand |
sleep rand |
||
puts x |
puts x |
||
} |
} |
||
}.each{ |
}.each{ |
||
|t| |
|t| |
Revision as of 17:17, 28 September 2007
You are encouraged to solve this task according to the task description, using any language you may know.
Using either native language concurrency syntax or freely available libraries write a program to display the strings "Enjoy" "Rosetta" "Code", one string per line, in random order. Concurrency syntax must use threads, tasks, co-routines, or whatever concurrency is called in your language.
Ada
Compiler:GNAT GPL 2006
with Ada.Text_Io; use Ada.Text_Io; with Ada.Numerics.Float_Random; use Ada.Numerics.Float_Random; with Ada.strings.Unbounded; use Ada.Strings.Unbounded; procedure Concurrent_Hello is Seed : Generator; task type Writer is entry Start(Message : String); end Writer; task body Writer is Sleep_Time : Float; Words : Unbounded_String; begin accept Start(Message : String) do Words := To_Unbounded_String(Message); end Start; Sleep_Time := Random(Seed); delay Duration(Sleep_Time); Put_Line(To_String(Words)); end Writer; T1 : Writer; T2 : Writer; T3 : Writer; begin Reset(Seed); delay 0.001; T1.Start("Enjoy"); T2.Start("Rosetta"); T3.Start("Code"); end Concurrent_Hello;
E
def base := timer.now() for string in ["Enjoy", "Rosetta", "Code"] { timer <- whenPast(base + entropy.nextInt(1000), fn { println(string) }) }
Nondeterminism from preemptive concurrency rather than a random number generator:
def seedVat := <import:org.erights.e.elang.interp.seedVatAuthor>(<unsafe>) for string in ["Enjoy", "Rosetta", "Code"] { seedVat <- (` fn string { println(string) currentVat <- orderlyShutdown("done") } `) <- get(0) <- (string) }
Forth
Interpreter: gforth 0.6.2
Many Forth implementations come with a simple cooperative task scheduler. Typically each task blocks on I/O or explicit use of the pause word. There is also a class of variables called "user" variables which contain task-specific data, such as the current base and stack pointers.
require tasker.fs require random.fs : task ( str len -- ) 64 NewTask 2 swap pass ( str len -- ) 10 0 do 100 random ms pause 2dup cr type loop 2drop ; : main s" Enjoy" task s" Rosetta" task s" Code" task begin pause single-tasking? until ; main
JavaScript
Interpreter: Firefox 2.0
var textbox = document.getElementsByTagName("textarea")[0]; setTimeout( function(){ textbox.value += "Enjoy\n"; }, Math.random() * 1000 ); setTimeout( function(){ textbox.value += "Rosetta\n"; }, Math.random() * 1000 ); setTimeout( function(){ textbox.value += "Code\n"; }, Math.random() * 1000 );
Perl
use threads; use Time::HiRes qw(sleep); $_->join for map { threads->create(sub { sleep rand; print shift, "\n"; }, $_) } qw(Enjoy Rosetta Code);
Python
Interpreter: Python 2.5
import threading import random def echo(string): print string threading.Timer(random.random(), echo, ("Enjoy",)).start() threading.Timer(random.random(), echo, ("Rosetta",)).start() threading.Timer(random.random(), echo, ("Code",)).start()
Ruby
%w{Enjoy Rosetta Code}.map{ |x| Thread.new{ sleep rand puts x } }.each{ |t| t.join }
Tcl
Assuming that "random" means that we really want the words to appear in random (rather then "undefined" or "arbitrary") order:
after [expr int(1000*rand())] {puts "Enjoy"} after [expr int(1000*rand())] {puts "Rosetta"} after [expr int(1000*rand())] {puts "Code"}
will execute each line after a randomly chosen number (0...1000) of milliseconds.
A step towards "undefined" would be to use after idle, which is Tcl for "do this whenever you get around to it". Thus:
after idle {puts "Enjoy"} after idle {puts "Rosetta"} after idle {puts "Code"}
(While no particular order is guaranteed by the Tcl spec, the currently existing interpreters would probably all execute these in the order in which they were added to the after queue).