Concurrent computing: Difference between revisions

From Rosetta Code
Content added Content deleted
(Haskell code added)
m (Switch to header template)
Line 4: Line 4:




==[[Ada]]==
=={{header|Ada}}==
[[Category: Ada]]
'''Compiler:GNAT''' GPL 2006
'''Compiler:GNAT''' GPL 2006


Line 41: Line 40:
end Concurrent_Hello;
end Concurrent_Hello;


==[[E]]==
=={{header|E}}==
[[Category:E]]

def base := timer.now()
def base := timer.now()
for string in ["Enjoy", "Rosetta", "Code"] {
for string in ["Enjoy", "Rosetta", "Code"] {
Line 61: Line 58:
}
}


==[[Forth]]==
=={{header|Forth}}==
[[Category:Forth]]
'''Interpreter:''' gforth 0.6.2
'''Interpreter:''' gforth 0.6.2


Line 85: Line 81:
main
main


==[[Groovy]]==
=={{Groovy}}==
[[Category:Groovy]]

'Enjoy Rosetta Code'.tokenize().collect { w ->
'Enjoy Rosetta Code'.tokenize().collect { w ->
Thread.start {
Thread.start {
Line 107: Line 101:
process3 = putStrLn "Code"
process3 = putStrLn "Code"


==[[JavaScript]]==
=={{header|JavaScript}}==
[[Category:JavaScript]]

'''Interpreter:''' Firefox 2.0
'''Interpreter:''' Firefox 2.0


Line 117: Line 109:
setTimeout( function(){ textbox.value += "Code\n"; }, Math.random() * 1000 );
setTimeout( function(){ textbox.value += "Code\n"; }, Math.random() * 1000 );


==[[Perl]]==
=={{header|Perl}}==
[[Category:Perl]]
use threads;
use threads;
use Time::HiRes qw(sleep);
use Time::HiRes qw(sleep);
Line 128: Line 119:
} qw(Enjoy Rosetta Code);
} qw(Enjoy Rosetta Code);


==[[Python]]==
=={{header|Python}}==
[[Category:Python]]

'''Interpreter:''' [[Python]] 2.5
'''Interpreter:''' [[Python]] 2.5


Line 143: Line 132:
threading.Timer(random.random(), echo, ("Code",)).start()
threading.Timer(random.random(), echo, ("Code",)).start()


==[[Raven]]==
=={{header|Raven}}==
[[Category:Raven]]

[ 'Enjoy' 'Rosetta' 'Code' ] as $words
[ 'Enjoy' 'Rosetta' 'Code' ] as $words
Line 157: Line 144:
talker as c
talker as c


==[[Ruby]]==
=={{header|Ruby}}==
[[Category:Ruby]]

%w{Enjoy Rosetta Code}.map{
%w{Enjoy Rosetta Code}.map{
|x|
|x|
Line 171: Line 156:
}
}


==[[Tcl]]==
=={{header|Tcl}}==
[[Category:Tcl]]

Assuming that "random" means that we really want the words to appear in random (rather then "undefined" or "arbitrary") order:
Assuming that "random" means that we really want the words to appear in random (rather then "undefined" or "arbitrary") order:



Revision as of 04:46, 13 November 2007

Task
Concurrent computing
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

Template:Groovy

'Enjoy Rosetta Code'.tokenize().collect { w ->
    Thread.start {
        Thread.sleep(1000 * Math.random() as int)
        println w
    }
}.each { it.join() }

Haskell

Note how the map treats the list of processes just like any other data.

import Control.Monad
import Control.Concurrent

main = sequence $ map forkIO $ [process1, process2, process3] where
  process1 = putStrLn "Enjoy" 
  process2 = putStrLn "Rosetta"
  process3 = putStrLn "Code"

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()

Raven

[ 'Enjoy' 'Rosetta' 'Code' ] as $words

thread talker
    $words pop "%s\n"
    repeat dup print
        500 choose ms

talker as a
talker as b
talker as c

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).