Concurrent computing
From Rosetta Code
You are encouraged to solve this task according to the task description, using any language you may know.
[edit] Ada
with Ada.Text_IO; use Ada.Text_IO;
with Ada.Numerics.Float_Random; use Ada.Numerics.Float_Random;
procedure Concurrent_Hello is
task type Writer (Message : access String);
task body Writer is
Seed : Generator;
begin
Reset (Seed); ''-- This is time-dependent, see Reference Manual A.5.2''
delay Duration (Random (Seed));
Put_Line (Message.all);
end Writer;
S1 : aliased String := "Enjoy";
S2 : aliased String := "Rosetta";
S3 : aliased String := "Code";
T1 : Writer (S1'Access);
T2 : Writer (S2'Access);
T3 : Writer (S3'Access);
begin
null;
end Concurrent_Hello;
Note that random generator object is local to each task. It cannot be accessed concurrently without mutual exclusion. In order to get different initial states of local generators Reset is called.
[edit] ALGOL 68
main:(
PROC echo = (STRING string)VOID:
printf(($gl$,string));
PAR(
echo("Enjoy"),
echo("Rosetta"),
echo("Code")
)
)
[edit] C
Works with: POSIX Library: pthread
#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
pthread_mutex_t condm = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
int bang = 0;
#define WAITBANG() do { \
pthread_mutex_lock(&condm); \
while( bang == 0 ) \
{ \
pthread_cond_wait(&cond, &condm); \
} \
pthread_mutex_unlock(&condm); } while(0);\
void *t_enjoy(void *p)
{
WAITBANG();
printf("Enjoy\n");
pthread_exit(0);
}
void *t_rosetta(void *p)
{
WAITBANG();
printf("Rosetta\n");
pthread_exit(0);
}
void *t_code(void *p)
{
WAITBANG();
printf("Code\n");
pthread_exit(0);
}
typedef void *(*threadfunc)(void *);
int main()
{
int i;
pthread_t a[3];
threadfunc p[3] = {t_enjoy, t_rosetta, t_code};
for(i=0;i<3;i++)
{
pthread_create(&a[i], NULL, p[i], NULL);
}
sleep(1);
bang = 1;
pthread_cond_broadcast(&cond);
for(i=0;i<3;i++)
{
pthread_join(a[i], NULL);
}
}
Note: since threads are created one after another, it is likely that the execution of their code follows the order of creation. To make this less evident, I've added the bang idea using condition: the thread really executes their code once the gun bang is heard. Nonetheless, I still obtain the same order of creation (Enjoy, Rosetta, Code), and maybe it is because of the order locks are acquired. The only way to obtain randomness seems to be to add random wait in each thread (or wait for special cpu load condition)
[edit] C#
static Random tRand = new Random();
static void Main(string[] args)
{
Thread t = new Thread(new ParameterizedThreadStart(WriteText));
t.Start("Enjoy");
t = new Thread(new ParameterizedThreadStart(WriteText));
t.Start("Rosetta");
t = new Thread(new ParameterizedThreadStart(WriteText));
t.Start("Code");
Console.ReadLine();
}
private static void WriteText(object p)
{
Thread.Sleep(tRand.Next(1000, 4000));
Console.WriteLine(p);
}
An example result:
Enjoy Code Rosetta
[edit] Clojure
A simple way to obtain concurrency is using the future function, which evaluates its body on a separate thread.
(doseq [text ["Enjoy" "Rosetta" "Code"]]
(future (println text)))
[edit] Common Lisp
Library: Bordeaux Threads
Concurrency and threads are not part of the Common Lisp standard. However, most implementations provide some interface for concurrency. Bordeaux Threads, used here, provides a compatibility layer for many implementations. (Binding out to *standard-output* before threads are created is needed as each thread gets its own binding for *standard-output*.)
(defun concurrency-example (&optional (out *standard-output*))
(let ((lock (bordeaux-threads:make-lock)))
(flet ((writer (string)
#'(lambda ()
(bordeaux-threads:acquire-lock lock t)
(write-line string out)
(bordeaux-threads:release-lock lock))))
(bordeaux-threads:make-thread (writer "Enjoy"))
(bordeaux-threads:make-thread (writer "Rosetta"))
(bordeaux-threads:make-thread (writer "Code")))))
[edit] D
Library: Tango
import tango.core.Thread;
import tango.io.Console;
import tango.math.Random;
void main() {
(new Thread( { Thread.sleep(Random.shared.next(1000) / 1000.0); Cout("Enjoy").newline; } )).start;
(new Thread( { Thread.sleep(Random.shared.next(1000) / 1000.0); Cout("Rosetta").newline; } )).start;
(new Thread( { Thread.sleep(Random.shared.next(1000) / 1000.0); Cout("Code").newline; } )).start;
}
[edit] 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)
}
[edit] Erlang
hw.erl
-module(hw).
-export([start/0]).
start() ->
[ spawn(fun() -> say(self(), X) end) || X <- ['Enjoy', 'Rosetta', 'Code'] ],
wait(2),
ok.
say(Pid,Str) ->
io:fwrite("~s~n",[Str]),
Pid ! done.
wait(N) ->
receive
done -> case N of
0 -> 0;
_N -> wait(N-1)
end
end.
running it
|erlc hw.erl
|erl -run hw start -run init stop -noshell
[edit] Factor
USE: concurrency.combinators
{ "Enjoy" "Rosetta" "Code" } [ print ] parallel-each
[edit] Forth
Works with: gforth version 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
[edit] Fortran
Fortran doesn't have threads but there are several compilers that support OpenMP, e.g. gfortran and Intel. The following code has been tested with thw Intel 11.1 compiler on WinXP.
program concurrency
implicit none
character(len=*), parameter :: str1 = 'Enjoy'
character(len=*), parameter :: str2 = 'Rosetta'
character(len=*), parameter :: str3 = 'Code'
integer :: i
real :: h
real, parameter :: one_third = 1.0e0/3
real, parameter :: two_thirds = 2.0e0/3
interface
integer function omp_get_thread_num
end function omp_get_thread_num
end interface
interface
integer function omp_get_num_threads
end function omp_get_num_threads
end interface
! Use OpenMP to create a team of threads
!$omp parallel do private(i,h)
do i=1,20
! First time through the master thread output the number of threads
! in the team
if (omp_get_thread_num() == 0 .and. i == 1) then
write(*,'(a,i0,a)') 'Using ',omp_get_num_threads(),' threads'
end if
! Randomize the order
call random_number(h)
!$omp critical
if (h < one_third) then
write(*,'(a)') str1
else if (h < two_thirds) then
write(*,'(a)') str2
else
write(*,'(a)') str3
end if
!$omp end critical
end do
!$omp end parallel do
end program concurrency
[edit] F#
We define a parallel version of Seq.iter by using asynchronous workflows:
module Seq =
let piter f xs =
seq { for x in xs -> async { f x } }
|> Async.Parallel
|> Async.RunSynchronously
|> ignore
let main() = Seq.piter
(System.Console.WriteLine:string->unit)
["Enjoy"; "Rosetta"; "Code";]
main()
With version 4 of the .NET framework and F# PowerPack 2.0 installed, it is possible to use the predefined PSeq.iter instead.
[edit] Go
When main() exits, that's it. To ensure completion of the go routines, it is necessary to wait for them. Note that the quit channel is shared, and so would w be, if not for the explicit local assignment. Another option would be to pass w to the closure as an argument.
package main
import (
"fmt"
"time"
"rand"
)
func main() {
words := []string{"Enjoy", "Rosetta", "Code"}
q := make(chan int)
rand.Seed(time.Nanoseconds())
for _, w := range words {
w := w
go func() {
time.Sleep(rand.Int63n(1e9))
fmt.Println(w)
q <- 0
}()
}
for i := 0; i < len(words); i++ {
<-q
}
}
[edit] Groovy
'Enjoy Rosetta Code'.tokenize().collect { w ->
Thread.start {
Thread.sleep(1000 * Math.random() as int)
println w
}
}.each { it.join() }
[edit] Haskell
Note how the map treats the list of processes just like any other data.
import Control.Concurrent
main = mapM_ forkIO [process1, process2, process3] where
process1 = putStrLn "Enjoy"
process2 = putStrLn "Rosetta"
process3 = putStrLn "Code"
[edit] Java
public class Threads{
public static void main(String[] args){
Thread enjoy =
new Thread(){
//this overridden method counts once every second up to five
public void run(){
System.out.println("Enjoy");
}
};
Thread rose =
new Thread(){
//this overridden method counts once every second up to five
public void run(){
System.out.println("Rosetta");
}
};
Thread code =
new Thread(){
//this overridden method counts once every second up to five
public void run(){
System.out.println("Code");
}
};
//these will probably (but not definitely) run in the order they are called since the runnable code is so short
enjoy.start(); //calling .run() will not run it in a new thread
rose.start();
code.start();
}
}
[edit] JavaScript
Works with: Firefox version 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 );
[edit] Mathematica
Parallelization requires Mathematica 7 or later
ParallelDo[
Pause[RandomReal[]];
Print[s],
{s, {"Enjoy", "Rosetta", "Code"}}
]
[edit] OCaml
#directory "+threads"
#load "unix.cma"
#load "threads.cma"
let sleepy_print msg =
Unix.sleep ( Random.int 4 );
print_endline msg
let threads = List.map ( Thread.create sleepy_print ) ["Enjoy"; "Rosetta"; "Code"];;
let () = List.iter ( Thread.join ) threads;;
[edit] Oz
The randomness comes from the unpredictability of thread scheduling (this is how I understand this exercise).
for Msg in ["Enjoy" "Rosetta" "Code"] do
thread
{System.showInfo Msg}
end
end
[edit] Perl
Library: Time::HiResHiRes
use threads;
use Time::HiRes qw(sleep);
$_->join for map {
threads->create(sub {
sleep rand;
print shift, "\n";
}, $_)
} qw(Enjoy Rosetta Code);
[edit] Perl 6
Works with: pugs
Hyper-operators are unordered:
my @words = <Enjoy Rosetta Code>;
@wordsยป.say
Output:
Rosetta
Code
Enjoy
[edit] PicoLisp
[edit] Using background tasks
(for (N . Str) '("Enjoy" "Rosetta" "Code")
(task (- N) (rand 1000 4000) # Random start time 1 .. 4 sec
Str Str # Closure with string value
(println Str) # Task body: Print the string
(task @) ) ) # and stop the task
[edit] Using child processes
(for Str '("Enjoy" "Rosetta" "Code")
(let N (rand 1000 4000) # Randomize
(unless (fork) # Create child process
(wait N) # Wait 1 .. 4 sec
(println Str) # Print string
(bye) ) ) ) # Terminate child process
[edit] PureBasic
Global mutex.i
mutex = CreateMutex()
Procedure t_enjoy(dummy.i)
LockMutex(mutex)
PrintN("enjoy")
UnlockMutex(mutex)
EndProcedure
Procedure t_rosetta(dummy.i)
LockMutex(mutex)
PrintN("rosetta")
UnlockMutex(mutex)
EndProcedure
Procedure t_code(dummy.i)
LockMutex(mutex)
PrintN("code")
UnlockMutex(mutex)
EndProcedure
LockMutex(mutex)
OpenConsole()
thread1 = CreateThread(@t_enjoy(), 0)
thread2 = CreateThread(@t_rosetta(), 0)
thread3 = CreateThread(@t_code(), 0)
UnlockMutex(mutex)
WaitThread(thread1)
WaitThread(thread2)
WaitThread(thread3)
Print(#CRLF$ + #CRLF$ + "Press ENTER to exit")
Input()
CloseConsole()
FreeMutex(mutex)
[edit] Python
Works with: Python version 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()
Or, by using a for loop to start one thread per list entry, where our list is our set of source strings:
import threading
import random
def echo(string):
print string
for text in ["Enjoy", "Rosetta", "Code"]:
threading.Timer(random.random(), echo, (text,)).start()
[edit] 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
[edit] Rhope
Works with: Rhope version alpha 1
Main(0,0)
|:
Print["Enjoy"]
Print["Rosetta"]
Print["Code"]
:|
In Rhope, expressions with no shared dependencies run in parallel by default.
[edit] Ruby
%w{Enjoy Rosetta Code}.map do |x|
Thread.new do
sleep rand
puts x
end
end.each do |t|
t.join
end
[edit] Scala
import scala.actors.Futures
List("Enjoy", "Rosetta", "Code").map { x =>
Futures.future {
Thread.sleep((Math.random * 1000).toInt)
println(x)
}
}.foreach(_())
[edit] Scheme
(parallel-execute (lambda () (print "Enjoy"))
(lambda () (print "Rosetta"))
(lambda () (print "Code")))
[edit] 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 current implementations will all execute these in the order in which they were added to the idle queue).
It's also possible to use threads for this. Here we do this with the built-in thread-pool support:
package require Thread
set pool [tpool::create -initcmd {
proc delayPrint msg {
after [expr int(1000*rand())]
puts $msg
}
}]
tpool::post -detached $pool [list delayPrint "Enjoy"]
tpool::post -detached $pool [list delayPrint "Rosetta"]
tpool::post -detached $pool [list delayPrint "Code"]
tpool::release $pool
after 1200 ;# Give threads time to do their work
exit
[edit] UnixPipes
(echo "Enjoy" & echo "Rosetta"& echo "Code"&)
[edit] Visual Basic .NET
Imports System.Threading
Module Module1
Public rnd As New Random
Sub Main()
Dim t1 As New Thread(AddressOf Foo)
Dim t2 As New Thread(AddressOf Foo)
Dim t3 As New Thread(AddressOf Foo)
t1.Start("Enjoy")
t2.Start("Rosetta")
t3.Start("Code")
t1.Join()
t2.Join()
t3.Join()
End Sub
Sub Foo(ByVal state As Object)
Thread.Sleep(rnd.Next(1000))
Console.WriteLine(state)
End Sub
End Module

