Jump to content

Concurrent computing

From Rosetta Code
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

<lang 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;</lang>

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.

ALGOL 68

main:(
  PROC echo = (STRING string)VOID:
      printf(($gl$,string));
  PAR(
    echo("Enjoy"),
    echo("Rosetta"),
    echo("Code")
  )
)

C

Works with: POSIX
Library: pthread

<lang c>#include <stdio.h>

  1. include <unistd.h>
  2. include <pthread.h>

pthread_mutex_t condm = PTHREAD_MUTEX_INITIALIZER; pthread_cond_t cond = PTHREAD_COND_INITIALIZER; int bang = 0;

  1. define WAITBANG() ({ \
  pthread_mutex_lock(&condm); \
  while( bang == 0 ) \
  { \
     pthread_cond_wait(&cond, &condm); \
  } \
  pthread_mutex_unlock(&condm); })\

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);
  }

}</lang>

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)

D

Library: Tango

<lang d>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;

}</lang>

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

Erlang

hw.erl

-module(hw).
-export([start/0, say/2, wait/1]).

start() ->
   spawn(hw, say, [self(), 'Enjoy']),
   spawn(hw, say, [self(), 'Rosetta']),
   spawn(hw, say, [self(), '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

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

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"


Java

<lang 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();
  }

}</lang>

JavaScript

Works with: Firefox version 2.0

<lang javascript>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 );</lang>

OCaml

<lang ocaml>#load "unix.cma"

  1. 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;; </lang>

Perl

<lang perl>use threads; use Time::HiRes qw(sleep);

$_->join for map {

   threads->create(sub {
       sleep rand;
       print shift, "\n";
   }, $_)

} qw(Enjoy Rosetta Code);</lang>

Python

Works with: Python version 2.5

<lang python>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()</lang>

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

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.

Ruby

<lang ruby>%w{Enjoy Rosetta Code}.map do |x|

   Thread.new do
       sleep rand
       puts x
   end

end.each do |t|

 t.join

end</lang>

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

UnixPipes

(echo "Enjoy" & echo "Rosetta"& echo "Code"&)

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
Cookies help us deliver our services. By using our services, you agree to our use of cookies.