Concurrent computing: Difference between revisions
(Haskell code added) |
m (→{{header|Wren}}: Changed to Wren S/H) |
||
(290 intermediate revisions by more than 100 users not shown) | |||
Line 1: | Line 1: | ||
{{task}} |
{{task|Concurrency}} |
||
[[Category:Basic language learning]] |
|||
;Task: |
|||
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. |
|||
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 [[thread|threads]], tasks, co-routines, or whatever concurrency is called in your language. |
|||
<br><br> |
|||
== |
=={{header|Ada}}== |
||
<syntaxhighlight lang="ada">with Ada.Text_IO, Ada.Numerics.Float_Random; |
|||
[[Category: Ada]] |
|||
'''Compiler:GNAT''' GPL 2006 |
|||
procedure Concurrent_Hello is |
|||
with Ada.Text_Io; use Ada.Text_Io; |
|||
type Messages is (Enjoy, Rosetta, Code); |
|||
with Ada.Numerics.Float_Random; use Ada.Numerics.Float_Random; |
|||
task type Writer (Message : Messages); |
|||
with Ada.strings.Unbounded; use Ada.Strings.Unbounded; |
|||
task body Writer is |
|||
Seed : Ada.Numerics.Float_Random.Generator; |
|||
procedure Concurrent_Hello is |
|||
begin |
|||
Seed : Generator; |
|||
Ada.Numerics.Float_Random.Reset (Seed); -- time-dependent, see ARM A.5.2 |
|||
delay Duration (Ada.Numerics.Float_Random.Random (Seed)); |
|||
task type Writer is |
|||
Ada.Text_IO.Put_Line (Messages'Image(Message)); |
|||
end Writer; |
|||
Taks: array(Messages) of access Writer -- 3 Writer tasks will immediately run |
|||
:= (new Writer(Enjoy), new Writer(Rosetta), new Writer(Code)); |
|||
task body Writer is |
|||
begin |
|||
Sleep_Time : Float; |
|||
null; -- the "environment task" doesn't need to do anything |
|||
Words : Unbounded_String; |
|||
end Concurrent_Hello;</syntaxhighlight> |
|||
begin |
|||
accept Start(Message : String) do |
|||
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 (see [http://www.adaic.org/resources/add_content/standards/05rm/html/RM-A-5-2.html ARM A.5.2]). |
|||
Words := To_Unbounded_String(Message); |
|||
end Start; |
|||
=={{header|ALGOL 68}}== |
|||
Sleep_Time := Random(Seed); |
|||
<syntaxhighlight lang="algol68">main:( |
|||
delay Duration(Sleep_Time); |
|||
PROC echo = (STRING string)VOID: |
|||
Put_Line(To_String(Words)); |
|||
printf(($gl$,string)); |
|||
end Writer; |
|||
PAR( |
|||
T1 : Writer; |
|||
echo("Enjoy"), |
|||
echo("Rosetta"), |
|||
T3 : Writer; |
|||
echo("Code") |
|||
begin |
|||
) |
|||
Reset(Seed); |
|||
)</syntaxhighlight> |
|||
delay 0.001; |
|||
T1.Start("Enjoy"); |
|||
=={{header|APL}}== |
|||
T2.Start("Rosetta"); |
|||
{{works with|Dyalog APL}} |
|||
T3.Start("Code"); |
|||
end Concurrent_Hello; |
|||
Dyalog APL supports the <code>&</code> operator, which runs a function on its own thread. |
|||
<syntaxhighlight lang="apl">{⎕←⍵}&¨'Enjoy' 'Rosetta' 'Code'</syntaxhighlight> |
|||
{{out}} |
|||
(Example) |
|||
<pre>Enjoy |
|||
Code |
|||
Rosetta</pre> |
|||
=={{header|Astro}}== |
|||
<syntaxhighlight lang="python">let words = ["Enjoy", "Rosetta", "Code"] |
|||
for word in words: |
|||
(word) |> async (w) => |
|||
sleep(random()) |
|||
print(w)</syntaxhighlight> |
|||
=={{header|BASIC}}== |
|||
==={{header|BaCon}}=== |
|||
{{libheader|gomp}} |
|||
{{works with|OpenMP}} |
|||
BaCon is a BASIC-to-C compiler. Assuming GCC compiler in this demonstration. Based on the C OpenMP source. |
|||
<syntaxhighlight lang="freebasic">' Concurrent computing using the OpenMP extension in GCC. Requires BaCon 3.6 or higher. |
|||
' Specify compiler flag |
|||
PRAGMA OPTIONS -fopenmp |
|||
' Sepcify linker flag |
|||
PRAGMA LDFLAGS -lgomp |
|||
' Declare array with text |
|||
DECLARE str$[] = { "Enjoy", "Rosetta", "Code" } |
|||
' Indicate MP optimization for FOR loop |
|||
PRAGMA omp parallel for num_threads(3) |
|||
' The actual FOR loop |
|||
FOR i = 0 TO 2 |
|||
PRINT str$[i] |
|||
NEXT |
|||
</syntaxhighlight> |
|||
{{out}} |
|||
<pre>prompt$ bacon concurrent-computing |
|||
Converting 'concurrent-computing.bac'... done, 11 lines were processed in 0.002 seconds. |
|||
Compiling 'concurrent-computing.bac'... cc -fopenmp -c concurrent-computing.bac.c |
|||
cc -o concurrent-computing concurrent-computing.bac.o -lbacon -lm -lgomp |
|||
Done, program 'concurrent-computing' ready. |
|||
prompt$ ./concurrent-computing |
|||
Code |
|||
Enjoy |
|||
Rosetta</pre> |
|||
==={{header|BBC BASIC}}=== |
|||
{{works with|BBC BASIC for Windows}} |
|||
The BBC BASIC interpreter is single-threaded so the only way of achieving 'concurrency' (short of using assembler code) is to use timer events: |
|||
<syntaxhighlight lang="bbcbasic"> INSTALL @lib$+"TIMERLIB" |
|||
tID1% = FN_ontimer(100, PROCtask1, 1) |
|||
tID2% = FN_ontimer(100, PROCtask2, 1) |
|||
tID3% = FN_ontimer(100, PROCtask3, 1) |
|||
ON ERROR PRINT REPORT$ : PROCcleanup : END |
|||
ON CLOSE PROCcleanup : QUIT |
|||
REPEAT |
|||
WAIT 0 |
|||
UNTIL FALSE |
|||
END |
|||
DEF PROCtask1 |
|||
PRINT "Enjoy" |
|||
ENDPROC |
|||
DEF PROCtask2 |
|||
PRINT "Rosetta" |
|||
ENDPROC |
|||
DEF PROCtask3 |
|||
PRINT "Code" |
|||
ENDPROC |
|||
DEF PROCcleanup |
|||
PROC_killtimer(tID1%) |
|||
PROC_killtimer(tID2%) |
|||
PROC_killtimer(tID3%) |
|||
ENDPROC</syntaxhighlight> |
|||
=={{header|C}}== |
|||
{{works with|POSIX}} |
|||
{{libheader|pthread}} |
|||
<syntaxhighlight lang="c">#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); |
|||
} |
|||
}</syntaxhighlight> |
|||
'''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) |
|||
===OpenMP=== |
|||
Compile with <code>gcc -std=c99 -fopenmp</code>: |
|||
<syntaxhighlight lang="c">#include <stdio.h> |
|||
#include <omp.h> |
|||
int main() |
|||
{ |
|||
const char *str[] = { "Enjoy", "Rosetta", "Code" }; |
|||
#pragma omp parallel for num_threads(3) |
|||
for (int i = 0; i < 3; i++) |
|||
printf("%s\n", str[i]); |
|||
return 0; |
|||
}</syntaxhighlight> |
|||
=={{header|C sharp|C#}}== |
|||
===With Threads=== |
|||
<syntaxhighlight lang="csharp"> |
|||
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); |
|||
} |
|||
</syntaxhighlight> |
|||
An example result: |
|||
<pre> |
|||
Enjoy |
|||
Code |
|||
Rosetta |
|||
</pre> |
|||
===With Tasks=== |
|||
{{works with|C sharp|7.1}} |
|||
<syntaxhighlight lang="csharp">using System; |
|||
using System.Threading.Tasks; |
|||
public class Program |
|||
{ |
|||
static async Task Main() { |
|||
Task t1 = Task.Run(() => Console.WriteLine("Enjoy")); |
|||
Task t2 = Task.Run(() => Console.WriteLine("Rosetta")); |
|||
Task t3 = Task.Run(() => Console.WriteLine("Code")); |
|||
await Task.WhenAll(t1, t2, t3); |
|||
} |
|||
}</syntaxhighlight> |
|||
===With a parallel loop=== |
|||
<syntaxhighlight lang="csharp">using System; |
|||
using System.Threading.Tasks; |
|||
public class Program |
|||
{ |
|||
static void Main() => Parallel.ForEach(new[] {"Enjoy", "Rosetta", "Code"}, s => Console.WriteLine(s)); |
|||
}</syntaxhighlight> |
|||
=={{header|C++}}== |
|||
{{works with|C++11}} |
|||
The following example compiles with GCC 4.7. |
|||
<code>g++ -std=c++11 -D_GLIBCXX_USE_NANOSLEEP -o concomp concomp.cpp</code> |
|||
<syntaxhighlight lang="cpp">#include <thread> |
|||
#include <iostream> |
|||
#include <vector> |
|||
#include <random> |
|||
#include <chrono> |
|||
int main() |
|||
{ |
|||
std::random_device rd; |
|||
std::mt19937 eng(rd()); // mt19937 generator with a hardware random seed. |
|||
std::uniform_int_distribution<> dist(1,1000); |
|||
std::vector<std::thread> threads; |
|||
for(const auto& str: {"Enjoy\n", "Rosetta\n", "Code\n"}) { |
|||
// between 1 and 1000ms per our distribution |
|||
std::chrono::milliseconds duration(dist(eng)); |
|||
threads.emplace_back([str, duration](){ |
|||
std::this_thread::sleep_for(duration); |
|||
std::cout << str; |
|||
}); |
|||
} |
|||
for(auto& t: threads) t.join(); |
|||
return 0; |
|||
}</syntaxhighlight> |
|||
Output: |
|||
<pre>Enjoy |
|||
Code |
|||
Rosetta</pre> |
|||
{{libheader|Microsoft Parallel Patterns Library (PPL)}} |
|||
<syntaxhighlight lang="cpp">#include <iostream> |
|||
#include <ppl.h> // MSVC++ |
|||
void a(void) { std::cout << "Eat\n"; } |
|||
void b(void) { std::cout << "At\n"; } |
|||
void c(void) { std::cout << "Joe's\n"; } |
|||
int main() |
|||
{ |
|||
// function pointers |
|||
Concurrency::parallel_invoke(&a, &b, &c); |
|||
// C++11 lambda functions |
|||
Concurrency::parallel_invoke( |
|||
[]{ std::cout << "Enjoy\n"; }, |
|||
[]{ std::cout << "Rosetta\n"; }, |
|||
[]{ std::cout << "Code\n"; } |
|||
); |
|||
return 0; |
|||
}</syntaxhighlight> |
|||
Output: |
|||
<pre> |
|||
Joe's |
|||
Eat |
|||
At |
|||
Enjoy |
|||
Code |
|||
Rosetta |
|||
</pre> |
|||
=={{header|Cind}}== |
|||
<syntaxhighlight lang="cind"> |
|||
execute() { |
|||
{# host.println("Enjoy"); |
|||
# host.println("Rosetta"); |
|||
# host.println("Code"); } |
|||
} |
|||
</syntaxhighlight> |
|||
=={{header|Clojure}}== |
|||
A simple way to obtain concurrency is using the ''future'' function, which evaluates its body on a separate thread. |
|||
<syntaxhighlight lang="clojure">(doseq [text ["Enjoy" "Rosetta" "Code"]] |
|||
(future (println text)))</syntaxhighlight> |
|||
Using the new (2013) ''core.async'' library, "go blocks" can execute asynchronously, |
|||
sharing threads from a pool. This works even in ClojureScript (the JavaScript target of Clojure) |
|||
on a single thread. The ''timeout'' call is there just to shuffle things up: note this delay doesn't block a thread. |
|||
<syntaxhighlight lang="clojure">(require '[clojure.core.async :refer [go <! timeout]]) |
|||
(doseq [text ["Enjoy" "Rosetta" "Code"]] |
|||
(go |
|||
(<! (timeout (rand-int 1000))) ; wait a random fraction of a second, |
|||
(println text)))</syntaxhighlight> |
|||
=={{header|CoffeeScript}}== |
|||
===Using Bash (or an equivalent shell)=== |
|||
{{works with|Node.js}} |
|||
{{works with|Bash}} |
|||
JavaScript, which CoffeeScript compiles to, is single-threaded. This approach launches multiple process to achieve concurrency on [http://nodejs.org Node.js]: |
|||
<syntaxhighlight lang="coffeescript">{ exec } = require 'child_process' |
|||
for word in [ 'Enjoy', 'Rosetta', 'Code' ] |
|||
exec "echo #{word}", (err, stdout) -> |
|||
console.log stdout</syntaxhighlight> |
|||
===Using Node.js=== |
|||
{{works with|Node.js}} |
|||
As stated above, CoffeeScript is single-threaded. This approach launches multiple [http://nodejs.org Node.js] processes to achieve concurrency. |
|||
<syntaxhighlight lang="coffeescript"># The "master" file. |
|||
{ fork } = require 'child_process' |
|||
path = require 'path' |
|||
child_name = path.join __dirname, 'child.coffee' |
|||
words = [ 'Enjoy', 'Rosetta', 'Code' ] |
|||
fork child_name, [ word ] for word in words</syntaxhighlight> |
|||
<syntaxhighlight lang="coffeescript"># child.coffee |
|||
console.log process.argv[ 2 ]</syntaxhighlight> |
|||
=={{header|Common Lisp}}== |
|||
{{libheader|Bordeaux Threads}} |
|||
Concurrency and threads are not part of the Common Lisp standard. However, most implementations provide some interface for concurrency. [http://common-lisp.net/project/bordeaux-threads/ Bordeaux Threads], used here, provides a compatibility layer for many implementations. (Binding <var>out</var> to <code>*standard-output*</code> before threads are created is needed as each thread gets its own binding for <code>*standard-output*</code>.) |
|||
<syntaxhighlight lang="lisp">(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")))))</syntaxhighlight> |
|||
=={{header|Crystal}}== |
|||
Crystal requires the use of channels to ensure that the main fiber doesn't exit before any of the new fibers are done, since each fiber sleeping could return control to the main fiber. |
|||
<syntaxhighlight lang="ruby">require "channel" |
|||
require "fiber" |
|||
require "random" |
|||
done = Channel(Nil).new |
|||
"Enjoy Rosetta Code".split.map do |x| |
|||
spawn do |
|||
sleep Random.new.rand(0..500).milliseconds |
|||
puts x |
|||
done.send nil |
|||
end |
|||
end |
|||
3.times do |
|||
done.receive |
|||
end</syntaxhighlight> |
|||
=={{header|D}}== |
|||
<syntaxhighlight lang="d">import std.stdio, std.random, std.parallelism, core.thread, core.time; |
|||
void main() { |
|||
foreach (s; ["Enjoy", "Rosetta", "Code"].parallel(1)) { |
|||
Thread.sleep(uniform(0, 1000).dur!"msecs"); |
|||
s.writeln; |
|||
} |
|||
}</syntaxhighlight> |
|||
===Alternative version=== |
|||
{{libheader|Tango}} |
|||
<syntaxhighlight 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; |
|||
}</syntaxhighlight> |
|||
=={{header|Dart}}== |
|||
===Future=== |
|||
Using Futures, called Promises in Javascript |
|||
<syntaxhighlight lang="javascript">import 'dart:math' show Random; |
|||
main(){ |
|||
enjoy() .then( (e) => print(e) ); |
|||
rosetta() .then( (r) => print(r) ); |
|||
code() .then( (c) => print(c) ); |
|||
} |
|||
// Create random number generator |
|||
var rng = Random(); |
|||
// Each function returns a future that starts after a delay |
|||
// Like using setTimeout with a Promise in Javascript |
|||
enjoy() => Future.delayed( Duration( milliseconds: rng.nextInt( 10 ) ), () => "Enjoy"); |
|||
rosetta() => Future.delayed( Duration( milliseconds: rng.nextInt( 10 ) ), () => "Rosetta"); |
|||
code() => Future.delayed( Duration( milliseconds: rng.nextInt( 10 ) ), () => "Code"); |
|||
</syntaxhighlight> |
|||
===Isolate=== |
|||
Using Isolates, similar to threads but each has its own memory, so they are more like Rust threads than C++ |
|||
<syntaxhighlight lang="javascript">import 'dart:isolate' show Isolate, ReceivePort; |
|||
import 'dart:io' show exit, sleep; |
|||
import 'dart:math' show Random; |
|||
main() { |
|||
// Create ReceivePort to receive done messages |
|||
// Called a channel in other languages |
|||
var receiver = ReceivePort(); |
|||
// Create job counter |
|||
var job_count = 3; |
|||
// Create job pool |
|||
var jobs = [ enjoy, rosetta, code ]; |
|||
// Create random number generator |
|||
var rng = Random(); |
|||
for ( var job in jobs ) { |
|||
// Sleep for random duration up to half a second |
|||
var sleep_time = Duration( milliseconds: rng.nextInt( 500 ) ); |
|||
// Spawn Isolate to do work |
|||
// When finished the second argument will be sent to the receiver via the SendPort specified in onExit |
|||
Isolate.spawn( job, sleep_time, onExit: receiver.sendPort ); |
|||
} |
|||
// Do something in main isolate |
|||
print("from main isolate\n"); |
|||
// Register a listener on the ReceivePort, it gets called whenver something is sent on its SendPort |
|||
// We'll ignore the message with _ because we don't care about the data, just the event |
|||
receiver.listen( (_) { |
|||
// Decrement job counter |
|||
job_count -= 1; |
|||
// If jobs are all finished |
|||
if ( job_count == 0 ) { |
|||
print("\nall jobs finished!"); |
|||
exit(0); |
|||
} |
|||
}); |
|||
} |
|||
enjoy ( duration ) { |
|||
==[[E]]== |
|||
sleep( duration ) ; |
|||
[[Category:E]] |
|||
print("Enjoy"); |
|||
} |
|||
rosetta ( duration ) { |
|||
def base := timer.now() |
|||
sleep( duration ); |
|||
for string in ["Enjoy", "Rosetta", "Code"] { |
|||
print("Rosetta"); |
|||
timer <- whenPast(base + entropy.nextInt(1000), fn { println(string) }) |
|||
} |
} |
||
code ( duration ) { |
|||
sleep( duration ); |
|||
print("Code"); |
|||
} |
|||
</syntaxhighlight> |
|||
=={{header|Delphi}}== |
|||
<syntaxhighlight lang="delphi">program ConcurrentComputing; |
|||
{$APPTYPE CONSOLE} |
|||
uses SysUtils, Classes, Windows; |
|||
type |
|||
TRandomThread = class(TThread) |
|||
private |
|||
FString: string; |
|||
protected |
|||
procedure Execute; override; |
|||
public |
|||
constructor Create(const aString: string); overload; |
|||
end; |
|||
constructor TRandomThread.Create(const aString: string); |
|||
begin |
|||
inherited Create(False); |
|||
FreeOnTerminate := True; |
|||
FString := aString; |
|||
end; |
|||
procedure TRandomThread.Execute; |
|||
begin |
|||
Sleep(Random(5) * 100); |
|||
Writeln(FString); |
|||
end; |
|||
var |
|||
lThreadArray: Array[0..2] of THandle; |
|||
begin |
|||
Randomize; |
|||
lThreadArray[0] := TRandomThread.Create('Enjoy').Handle; |
|||
lThreadArray[1] := TRandomThread.Create('Rosetta').Handle; |
|||
lThreadArray[2] := TRandomThread.Create('Stone').Handle; |
|||
WaitForMultipleObjects(Length(lThreadArray), @lThreadArray, True, INFINITE); |
|||
end.</syntaxhighlight> |
|||
=={{header|dodo0}}== |
|||
<syntaxhighlight lang="dodo0">fun parprint -> text, return |
|||
( |
|||
fork() -> return, throw |
|||
println(text, return) |
|||
| x |
|||
return() |
|||
) |
|||
| parprint |
|||
parprint("Enjoy") -> |
|||
parprint("Rosetta") -> |
|||
parprint("Code") -> |
|||
exit()</syntaxhighlight> |
|||
=={{header|E}}== |
|||
<syntaxhighlight lang="e">def base := timer.now() |
|||
for string in ["Enjoy", "Rosetta", "Code"] { |
|||
timer <- whenPast(base + entropy.nextInt(1000), fn { println(string) }) |
|||
}</syntaxhighlight> |
|||
Nondeterminism from preemptive concurrency rather than a random number generator: |
Nondeterminism from preemptive concurrency rather than a random number generator: |
||
<syntaxhighlight lang="e">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) |
|||
}</syntaxhighlight> |
|||
} |
|||
=={{header|EchoLisp}}== |
|||
==[[Forth]]== |
|||
<syntaxhighlight lang="scheme"> |
|||
[[Category:Forth]] |
|||
(lib 'tasks) ;; use the tasks library |
|||
'''Interpreter:''' gforth 0.6.2 |
|||
(define (tprint line ) ;; task definition |
|||
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. |
|||
(writeln _TASK line) |
|||
#f ) |
|||
(for-each task-run ;; run three // tasks |
|||
(map (curry make-task tprint) '(Enjoy Rosetta code ))) |
|||
→ |
|||
require tasker.fs |
|||
#task:id:66:running Rosetta |
|||
require random.fs |
|||
#task:id:67:running code |
|||
#task:id:65:running Enjoy |
|||
</syntaxhighlight> |
|||
64 NewTask 2 swap pass |
|||
( str len -- ) |
|||
=={{header|Egel}}== |
|||
10 0 do |
|||
<syntaxhighlight lang="egel"> |
|||
100 random ms |
|||
import "prelude.eg" |
|||
pause 2dup cr type |
|||
import "io.ego" |
|||
loop 2drop ; |
|||
using System |
|||
using IO |
|||
def main = |
|||
let _ = par (par [_ -> print "enjoy\n"] |
|||
[_ -> print "rosetta\n"]) |
|||
[_ -> print "code\n"] in nop |
|||
</syntaxhighlight> |
|||
=={{header|Elixir}}== |
|||
<syntaxhighlight lang="elixir">defmodule Concurrent do |
|||
def computing(xs) do |
|||
Enum.each(xs, fn x -> |
|||
spawn(fn -> |
|||
Process.sleep(:rand.uniform(1000)) |
|||
IO.puts x |
|||
end) |
|||
end) |
|||
Process.sleep(1000) |
|||
end |
|||
end |
|||
Concurrent.computing ["Enjoy", "Rosetta", "Code"]</syntaxhighlight> |
|||
: main |
|||
s" Enjoy" task |
|||
s" Rosetta" task |
|||
s" Code" task |
|||
begin pause single-tasking? until ; |
|||
main |
|||
{{out}} |
|||
==[[Groovy]]== |
|||
<pre> |
|||
[[Category:Groovy]] |
|||
Rosetta |
|||
Code |
|||
Enjoy |
|||
</pre> |
|||
=={{header|Erlang}}== |
|||
'Enjoy Rosetta Code'.tokenize().collect { w -> |
|||
hw.erl |
|||
Thread.start { |
|||
<syntaxhighlight lang="erlang">-module(hw). |
|||
Thread.sleep(1000 * Math.random() as int) |
|||
-export([start/0]). |
|||
println w |
|||
} |
|||
start() -> |
|||
}.each { it.join() } |
|||
[ 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.</syntaxhighlight> |
|||
running it |
|||
<syntaxhighlight lang="erlang">|erlc hw.erl |
|||
|erl -run hw start -run init stop -noshell</syntaxhighlight> |
|||
=={{header|Euphoria}}== |
|||
<syntaxhighlight lang="euphoria">procedure echo(sequence s) |
|||
puts(1,s) |
|||
puts(1,'\n') |
|||
end procedure |
|||
atom task1,task2,task3 |
|||
task1 = task_create(routine_id("echo"),{"Enjoy"}) |
|||
task_schedule(task1,1) |
|||
task2 = task_create(routine_id("echo"),{"Rosetta"}) |
|||
task_schedule(task2,1) |
|||
task3 = task_create(routine_id("echo"),{"Code"}) |
|||
task_schedule(task3,1) |
|||
task_yield()</syntaxhighlight> |
|||
Output: |
|||
Code |
|||
Rosetta |
|||
Enjoy |
|||
=={{header|F_Sharp|F#}}== |
|||
We define a parallel version of <code>Seq.iter</code> by using asynchronous workflows: |
|||
<syntaxhighlight lang="fsharp">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()</syntaxhighlight> |
|||
With version 4 of the .NET framework and F# PowerPack 2.0 installed, it is possible to use the predefined <code>PSeq.iter</code> instead. |
|||
=={{header|Factor}}== |
|||
<syntaxhighlight lang="factor">USE: concurrency.combinators |
|||
{ "Enjoy" "Rosetta" "Code" } [ print ] parallel-each</syntaxhighlight> |
|||
=={{header|Forth}}== |
|||
{{works with|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. |
|||
<syntaxhighlight lang="forth">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</syntaxhighlight> |
|||
=={{header|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. |
|||
<syntaxhighlight lang="fortran">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</syntaxhighlight> |
|||
=={{header|FreeBASIC}}== |
|||
<syntaxhighlight lang="freebasic">' FB 1.05.0 Win64 |
|||
' Compiled with -mt switch (to use threadsafe runtiume) |
|||
' The 'ThreadCall' functionality in FB is based internally on LibFFi (see [https://github.com/libffi/libffi/blob/master/LICENSE] for license) |
|||
Sub thread1() |
|||
Print "Enjoy" |
|||
End Sub |
|||
Sub thread2() |
|||
Print "Rosetta" |
|||
End Sub |
|||
Sub thread3() |
|||
Print "Code" |
|||
End Sub |
|||
Print "Press any key to print next batch of 3 strings or ESC to quit" |
|||
Print |
|||
Do |
|||
Dim t1 As Any Ptr = ThreadCall thread1 |
|||
Dim t2 As Any Ptr = ThreadCall thread2 |
|||
Dim t3 As Any Ptr = ThreadCall thread3 |
|||
ThreadWait t1 |
|||
ThreadWait t2 |
|||
ThreadWait t3 |
|||
Print |
|||
Sleep |
|||
Loop While Inkey <> Chr(27)</syntaxhighlight> |
|||
Sample output |
|||
{{out}} |
|||
<pre> |
|||
Press any key to print next batch of 3 strings or ESC to quit |
|||
Enjoy |
|||
Code |
|||
Rosetta |
|||
Enjoy |
|||
Rosetta |
|||
Code |
|||
</pre> |
|||
=={{header|FutureBasic}}== |
|||
<syntaxhighlight lang="futurebasic"> |
|||
include "NSLog.incl" |
|||
long priority(2) |
|||
priority(0) = _dispatchPriorityDefault |
|||
priority(1) = _dispatchPriorityHigh |
|||
priority(2) = _dispatchPriorityLow |
|||
dispatchglobal , priority(rnd(3)-1) |
|||
NSLog(@"Enjoy") |
|||
dispatchend |
|||
dispatchglobal , priority(rnd(3)-1) |
|||
NSLog(@"Rosetta") |
|||
dispatchend |
|||
dispatchglobal , priority(rnd(3)-1) |
|||
NSLog(@"Code") |
|||
dispatchend |
|||
HandleEvents |
|||
</syntaxhighlight> |
|||
=={{header|Go}}== |
|||
===Channel=== |
|||
Simple and direct solution: Start three goroutines, give each one a word. Each sleeps, then returns the word on a channel. The main goroutine prints words as they return. The print loop represents a [[Checkpoint_synchronization|checkpoint]] -- main doesn't exit until all words have been returned and printed. |
|||
This solution also shows a good practice for generating random numbers in concurrent goroutines. While certainly not needed for this RC task, in the more general case where you have a number of goroutines concurrently needing random numbers, the goroutines can suffer congestion if they compete heavily for the sole default library source. This can be relieved by having each goroutine create its own non-sharable source. Also particularly in cases where there might be a large number of concurrent goroutines, the source provided in subrepository rand package (exp/rand) can be a better choice than the standard library generator. The subrepo generator requires much less memory for "state" and is much faster to seed. |
|||
<syntaxhighlight lang="go">package main |
|||
import ( |
|||
"fmt" |
|||
"golang.org/x/exp/rand" |
|||
"time" |
|||
) |
|||
func main() { |
|||
words := []string{"Enjoy", "Rosetta", "Code"} |
|||
seed := uint64(time.Now().UnixNano()) |
|||
q := make(chan string) |
|||
for i, w := range words { |
|||
go func(w string, seed uint64) { |
|||
r := rand.New(rand.NewSource(seed)) |
|||
time.Sleep(time.Duration(r.Int63n(1e9))) |
|||
q <- w |
|||
}(w, seed+uint64(i)) |
|||
} |
|||
for i := 0; i < len(words); i++ { |
|||
fmt.Println(<-q) |
|||
} |
|||
}</syntaxhighlight> |
|||
===Afterfunc=== |
|||
time.Afterfunc combines the sleep and the goroutine start. log.Println serializes output in the case goroutines attempt to print concurrently. sync.WaitGroup is used directly as a checkpoint. |
|||
<syntaxhighlight lang="go">package main |
|||
import ( |
|||
"log" |
|||
"math/rand" |
|||
"os" |
|||
"sync" |
|||
"time" |
|||
) |
|||
func main() { |
|||
words := []string{"Enjoy", "Rosetta", "Code"} |
|||
rand.Seed(time.Now().UnixNano()) |
|||
l := log.New(os.Stdout, "", 0) |
|||
var q sync.WaitGroup |
|||
q.Add(len(words)) |
|||
for _, w := range words { |
|||
w := w |
|||
time.AfterFunc(time.Duration(rand.Int63n(1e9)), func() { |
|||
l.Println(w) |
|||
q.Done() |
|||
}) |
|||
} |
|||
q.Wait() |
|||
}</syntaxhighlight> |
|||
===Select=== |
|||
This solution might stretch the intent of the task a bit. It is concurrent but not parallel. Also it doesn't sleep and doesn't call the random number generator explicity. It works because the select statement is specified to make a "pseudo-random fair choice" among |
|||
multiple channel operations. |
|||
<syntaxhighlight lang="go">package main |
|||
import "fmt" |
|||
func main() { |
|||
w1 := make(chan bool, 1) |
|||
w2 := make(chan bool, 1) |
|||
w3 := make(chan bool, 1) |
|||
for i := 0; i < 3; i++ { |
|||
w1 <- true |
|||
w2 <- true |
|||
w3 <- true |
|||
fmt.Println() |
|||
for i := 0; i < 3; i++ { |
|||
select { |
|||
case <-w1: |
|||
fmt.Println("Enjoy") |
|||
case <-w2: |
|||
fmt.Println("Rosetta") |
|||
case <-w3: |
|||
fmt.Println("Code") |
|||
} |
|||
} |
|||
} |
|||
}</syntaxhighlight> |
|||
Output: |
|||
<pre> |
|||
Code |
|||
Rosetta |
|||
Enjoy |
|||
Enjoy |
|||
Rosetta |
|||
Code |
|||
Rosetta |
|||
Enjoy |
|||
Code |
|||
</pre> |
|||
=={{header|Groovy}}== |
|||
<syntaxhighlight lang="groovy">'Enjoy Rosetta Code'.tokenize().collect { w -> |
|||
Thread.start { |
|||
Thread.sleep(1000 * Math.random() as int) |
|||
println w |
|||
} |
|||
}.each { it.join() }</syntaxhighlight> |
|||
=={{header|Haskell}}== |
=={{header|Haskell}}== |
||
Line 99: | Line 988: | ||
Note how the map treats the list of processes just like any other data. |
Note how the map treats the list of processes just like any other data. |
||
<syntaxhighlight lang="haskell">import Control.Concurrent |
|||
import Control.Concurrent |
|||
main = sequence $ map forkIO $ [process1, process2, process3] where |
|||
process1 = putStrLn "Enjoy" |
|||
process2 = putStrLn "Rosetta" |
|||
process3 = putStrLn "Code" |
|||
main = mapM_ forkIO [process1, process2, process3] where |
|||
==[[JavaScript]]== |
|||
process1 = putStrLn "Enjoy" |
|||
[[Category:JavaScript]] |
|||
process2 = putStrLn "Rosetta" |
|||
process3 = putStrLn "Code"</syntaxhighlight> |
|||
A more elaborated example using MVars and a random running time per thread. |
|||
'''Interpreter:''' Firefox 2.0 |
|||
<syntaxhighlight lang="haskell">import Control.Concurrent |
|||
var textbox = document.getElementsByTagName("textarea")[0]; |
|||
import System.Random |
|||
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 ); |
|||
concurrent :: IO () |
|||
==[[Perl]]== |
|||
concurrent = do |
|||
[[Category:Perl]] |
|||
var <- newMVar [] -- use an MVar to collect the results of each thread |
|||
use threads; |
|||
mapM_ (forkIO . task var) ["Enjoy", "Rosetta", "Code"] -- run 3 threads |
|||
use Time::HiRes qw(sleep); |
|||
putStrLn "Press Return to show the results." -- while we wait for the user, |
|||
$_->join for map { |
|||
threads |
-- the threads run |
||
_ <- getLine |
|||
takeMVar var >>= mapM_ putStrLn -- read the results and show them on screen |
|||
print shift, "\n"; |
|||
where |
|||
-- "task" is a thread |
|||
} qw(Enjoy Rosetta Code); |
|||
task v s = do |
|||
randomRIO (1,10) >>= \r -> threadDelay (r * 100000) -- wait a while |
|||
val <- takeMVar v -- read the MVar and block other threads from reading it |
|||
-- until we write another value to it |
|||
putMVar v (s : val) -- append a text string to the MVar and block other |
|||
-- threads from writing to it unless it is read first</syntaxhighlight> |
|||
==Icon and {{header|Unicon}}== |
|||
==[[Python]]== |
|||
The following code uses features exclusive to Unicon |
|||
[[Category:Python]] |
|||
<syntaxhighlight lang="unicon">procedure main() |
|||
L:=[ thread write("Enjoy"), thread write("Rosetta"), thread write("Code") ] |
|||
every wait(!L) |
|||
end</syntaxhighlight> |
|||
=={{header|J}}== |
|||
'''Interpreter:''' [[Python]] 2.5 |
|||
Using J's new threading primitives (in place of some sort of thread emulation): |
|||
import threading |
|||
import random |
|||
<syntaxhighlight lang=J>reqthreads=: {{ 0&T.@''^:(0>.y-1 T.'')0 }} |
|||
dispatchwith=: (t.'')every |
|||
newmutex=: 10&T. |
|||
lock=: 11&T. |
|||
unlock=: 13&T. |
|||
synced=: {{ |
|||
lock n |
|||
r=. u y |
|||
unlock n |
|||
r |
|||
}} |
|||
register=: {{ out=: out, y }} synced (newmutex 0) |
|||
task=: {{ |
|||
reqthreads 3 NB. at least 3 worker threads |
|||
out=: EMPTY |
|||
#@> register dispatchwith ;:'Enjoy Rosetta Code' |
|||
out |
|||
}}</syntaxhighlight> |
|||
Sample use: |
|||
<syntaxhighlight lang=J> task'' |
|||
Enjoy |
|||
Rosetta |
|||
Code |
|||
task'' |
|||
Enjoy |
|||
Code |
|||
Rosetta</syntaxhighlight> |
|||
=={{header|Java}}== |
|||
Create a new <code>Thread</code> array, shuffle the array, start each thread. |
|||
<syntaxhighlight lang="java"> |
|||
Thread[] threads = new Thread[3]; |
|||
threads[0] = new Thread(() -> System.out.println("enjoy")); |
|||
threads[1] = new Thread(() -> System.out.println("rosetta")); |
|||
threads[2] = new Thread(() -> System.out.println("code")); |
|||
Collections.shuffle(Arrays.asList(threads)); |
|||
for (Thread thread : threads) |
|||
thread.start(); |
|||
</syntaxhighlight> |
|||
<br /> |
|||
An alternate demonstration |
|||
{{works with|Java|1.5+}} |
|||
Uses CyclicBarrier to force all threads to wait until they're at the same point before executing the println, increasing the odds they'll print in a different order (otherwise, while the they may be executing in parallel, the threads are started sequentially and with such a short run-time, will usually output sequentially as well). |
|||
<syntaxhighlight lang="java5">import java.util.concurrent.CyclicBarrier; |
|||
public class Threads |
|||
{ |
|||
public static class DelayedMessagePrinter implements Runnable |
|||
{ |
|||
private CyclicBarrier barrier; |
|||
private String msg; |
|||
public DelayedMessagePrinter(CyclicBarrier barrier, String msg) |
|||
{ |
|||
this.barrier = barrier; |
|||
this.msg = msg; |
|||
} |
|||
public void run() |
|||
{ |
|||
try |
|||
{ barrier.await(); } |
|||
catch (Exception e) |
|||
{ } |
|||
System.out.println(msg); |
|||
} |
|||
} |
|||
public static void main(String[] args) |
|||
def echo(string): |
|||
{ |
|||
print string |
|||
CyclicBarrier barrier = new CyclicBarrier(3); |
|||
new Thread(new DelayedMessagePrinter(barrier, "Enjoy")).start(); |
|||
new Thread(new DelayedMessagePrinter(barrier, "Rosetta")).start(); |
|||
new Thread(new DelayedMessagePrinter(barrier, "Code")).start(); |
|||
} |
|||
}</syntaxhighlight> |
|||
=={{header|JavaScript}}== |
|||
JavaScript now enjoys access to a concurrency library thanks to [http://en.wikipedia.org/wiki/Web_worker Web Workers]. The Web Workers specification defines an API for spawning background scripts. This first code is the background script and should be in the concurrent_worker.js file. |
|||
<syntaxhighlight lang="javascript">self.addEventListener('message', function (event) { |
|||
self.postMessage(event.data); |
|||
self.close(); |
|||
}, false);</syntaxhighlight> |
|||
This second block creates the workers, sends them a message and creates an event listener to handle the response. |
|||
<syntaxhighlight lang="javascript">var words = ["Enjoy", "Rosetta", "Code"]; |
|||
var workers = []; |
|||
for (var i = 0; i < words.length; i++) { |
|||
workers[i] = new Worker("concurrent_worker.js"); |
|||
workers[i].addEventListener('message', function (event) { |
|||
console.log(event.data); |
|||
}, false); |
|||
workers[i].postMessage(words[i]); |
|||
}</syntaxhighlight> |
|||
=={{header|Julia}}== |
|||
{{works with|Julia|0.6}} |
|||
<syntaxhighlight lang="julia">words = ["Enjoy", "Rosetta", "Code"] |
|||
function sleepprint(s) |
|||
sleep(rand()) |
|||
println(s) |
|||
end |
|||
@sync for word in words |
|||
@async sleepprint(word) |
|||
end</syntaxhighlight> |
|||
=={{header|Kotlin}}== |
|||
{{trans|Java}} |
|||
<syntaxhighlight lang="scala">// version 1.1.2 |
|||
import java.util.concurrent.CyclicBarrier |
|||
class DelayedMessagePrinter(val barrier: CyclicBarrier, val msg: String) : Runnable { |
|||
override fun run() { |
|||
barrier.await() |
|||
println(msg) |
|||
} |
|||
} |
|||
fun main(args: Array<String>) { |
|||
val msgs = listOf("Enjoy", "Rosetta", "Code") |
|||
val barrier = CyclicBarrier(msgs.size) |
|||
for (msg in msgs) Thread(DelayedMessagePrinter(barrier, msg)).start() |
|||
}</syntaxhighlight> |
|||
{{out}} |
|||
Sample output: |
|||
<pre> |
|||
Code |
|||
Rosetta |
|||
Enjoy |
|||
</pre> |
|||
=={{header|LFE}}== |
|||
<syntaxhighlight lang="lisp"> |
|||
;;; |
|||
;;; This is a straight port of the Erlang version. |
|||
;;; |
|||
;;; You can run this under the LFE REPL as follows: |
|||
;;; |
|||
;;; (slurp "concurrent-computing.lfe") |
|||
;;; (start) |
|||
;;; |
|||
(defmodule concurrent-computing |
|||
(export (start 0))) |
|||
(defun start () |
|||
(lc ((<- word '("Enjoy" "Rosetta" "Code"))) |
|||
(spawn (lambda () (say (self) word)))) |
|||
(wait 2) |
|||
'ok) |
|||
(defun say (pid word) |
|||
(lfe_io:format "~p~n" (list word)) |
|||
(! pid 'done)) |
|||
(defun wait (n) |
|||
(receive |
|||
('done (case n |
|||
(0 0) |
|||
(_n (wait (- n 1))))))) |
|||
</syntaxhighlight> |
|||
=={{header|Logtalk}}== |
|||
Works when using SWI-Prolog, XSB, or YAP as the backend compiler. |
|||
<syntaxhighlight lang="logtalk">:- object(concurrency). |
|||
:- initialization(output). |
|||
output :- |
|||
threaded(( |
|||
write('Enjoy'), |
|||
write('Rosetta'), |
|||
write('Code') |
|||
)). |
|||
:- end_object.</syntaxhighlight> |
|||
=={{header|Lua}}== |
|||
<syntaxhighlight lang="lua">co = {} |
|||
co[1] = coroutine.create( function() print "Enjoy" end ) |
|||
co[2] = coroutine.create( function() print "Rosetta" end ) |
|||
co[3] = coroutine.create( function() print "Code" end ) |
|||
math.randomseed( os.time() ) |
|||
h = {} |
|||
i = 0 |
|||
repeat |
|||
j = math.random(3) |
|||
if h[j] == nil then |
|||
coroutine.resume( co[j] ) |
|||
h[j] = true |
|||
i = i + 1 |
|||
end |
|||
until i == 3</syntaxhighlight> |
|||
=={{header|M2000 Interpreter}}== |
|||
Each thread executed in same scope where created. We can use static variables, which are at thread level, so in this example we have three A$,one for each thread. Each thread can use Thread This to send command, or using a known handler (number which return to k) to execute commands to other threads. Commands are HOLD,RESTART, ERASE, INTERVAL, EXECUTE. |
|||
Each thread has own stack of values, which deleted when erased. We can '''Push''' values to top of stack, or use '''Data''' to push to end of stack. A '''Read''' statement read from top of stack. In the example we Flush module's stack (modules use parent stack, functions get own stack), we place with Data strings and we read it using Read M$. We place the M$ to Static A$ (this can be done one time, because if A$ as static exist then interpreter skip expression without execute it). |
|||
All threads of a module erased when a module exit. Any block of code inside { } in Thread run without concurrency, when we use Thread.Plan Concurrent (when a thread runs we can't change Plan). Other plan is the sequential. Interval can be set to milliseconds. |
|||
Threads actually runs in Wait loop. We can use Main.Task as a loop which is thread also. Threads can be run when we wait for input in m2000 console, or for events from M2000 GUI forms, also. Events always run in sequential form. |
|||
<syntaxhighlight lang="m2000 interpreter"> |
|||
Thread.Plan Concurrent |
|||
Module CheckIt { |
|||
Flush \\ empty stack of values |
|||
Data "Enjoy", "Rosetta", "Code" |
|||
For i=1 to 3 { |
|||
Thread { |
|||
Print A$ |
|||
Thread This Erase |
|||
} As K |
|||
Read M$ |
|||
Thread K Execute Static A$=M$ |
|||
Thread K Interval Random(500,1000) |
|||
Threads |
|||
} |
|||
Rem : Wait 3000 ' we can use just a wait loop, or the main.task loop |
|||
\\ main.task exit if all threads erased |
|||
Main.Task 30 { |
|||
} |
|||
\\ when module exit all threads from this module get a signal to stop. |
|||
\\ we can use Threads Erase to erase all threads. |
|||
\\ Also if we press Esc we do the same |
|||
} |
|||
CheckIt |
|||
\\ we can define again the module, and now we get three time each name, but not every time three same names. |
|||
\\ if we change to Threads.Plan Sequential we get always the three same names |
|||
\\ Also in concurrent plan we can use a block to ensure that statements run without other thread executed in parallel. |
|||
Module CheckIt { |
|||
Flush \\ empty stack of values |
|||
Data "Enjoy", "Rosetta", "Code" |
|||
For i=1 to 3 { |
|||
Thread { |
|||
Print A$ |
|||
Print A$ |
|||
Print A$ |
|||
Thread This Erase |
|||
} As K |
|||
Read M$ |
|||
Thread K Execute Static A$=M$ |
|||
Thread K Interval Random(500,530) |
|||
Threads |
|||
} |
|||
Rem : Wait 3000 ' we can use just a wait loop, or the main.task loop |
|||
\\ main.task exit if all threads erased |
|||
Main.Task 30 { |
|||
} |
|||
\\ when module exit all threads from this module get a signal to stop. |
|||
\\ we can use Threads Erase to erase all threads. |
|||
\\ Also if we press Esc we do the same |
|||
} |
|||
CheckIt |
|||
</syntaxhighlight> |
|||
=={{header|Mathematica}} / {{header|Wolfram Language}}== |
|||
Parallelization requires Mathematica 7 or later |
|||
<syntaxhighlight lang="mathematica">ParallelDo[ |
|||
Pause[RandomReal[]]; |
|||
Print[s], |
|||
{s, {"Enjoy", "Rosetta", "Code"}} |
|||
]</syntaxhighlight> |
|||
=={{header|Mercury}}== |
|||
<syntaxhighlight lang="text">:- module concurrent_computing. |
|||
:- interface. |
|||
:- import_module io. |
|||
:- pred main(io::di, io::uo) is cc_multi. |
|||
:- implementation. |
|||
:- import_module thread. |
|||
main(!IO) :- |
|||
spawn(io.print_cc("Enjoy\n"), !IO), |
|||
spawn(io.print_cc("Rosetta\n"), !IO), |
|||
spawn(io.print_cc("Code\n"), !IO).</syntaxhighlight> |
|||
=={{header|Neko}}== |
|||
<syntaxhighlight lang="actionscript">/** |
|||
Concurrent computing, in Neko |
|||
*/ |
|||
var thread_create = $loader.loadprim("std@thread_create", 2); |
|||
var subtask = function(message) { |
|||
$print(message, "\n"); |
|||
} |
|||
/* The thread functions happen so fast as to look sequential */ |
|||
thread_create(subtask, "Enjoy"); |
|||
thread_create(subtask, "Rosetta"); |
|||
thread_create(subtask, "Code"); |
|||
/* slow things down */ |
|||
var sys_sleep = $loader.loadprim("std@sys_sleep", 1); |
|||
var random_new = $loader.loadprim("std@random_new", 0); |
|||
var random_int = $loader.loadprim("std@random_int", 2); |
|||
var randomsleep = function(message) { |
|||
var r = random_new(); |
|||
var sleep = random_int(r, 3); |
|||
sys_sleep(sleep); |
|||
$print(message, "\n"); |
|||
} |
|||
$print("\nWith random delays\n"); |
|||
thread_create(randomsleep, "Enjoy"); |
|||
thread_create(randomsleep, "Rosetta"); |
|||
thread_create(randomsleep, "Code"); |
|||
/* Let the threads complete */ |
|||
sys_sleep(4);</syntaxhighlight> |
|||
{{out}} |
|||
<pre>prompt$ nekoc threading.neko |
|||
prompt$ neko threading |
|||
Enjoy |
|||
Rosetta |
|||
Code |
|||
With random delays |
|||
Rosetta |
|||
Enjoy |
|||
Code</pre> |
|||
=={{header|Nim}}== |
|||
Compile with <code>nim --threads:on c concurrent</code>: |
|||
<syntaxhighlight lang="nim">const str = ["Enjoy", "Rosetta", "Code"] |
|||
var thr: array[3, Thread[int32]] |
|||
proc f(i:int32) {.thread.} = |
|||
echo str[i] |
|||
for i in 0..thr.high: |
|||
createThread(thr[i], f, int32(i)) |
|||
joinThreads(thr)</syntaxhighlight> |
|||
===OpenMP=== |
|||
Compile with <code>nim --passC:"-fopenmp" --passL:"-fopenmp" c concurrent</code>: |
|||
<syntaxhighlight lang="nim">const str = ["Enjoy", "Rosetta", "Code"] |
|||
for i in 0||2: |
|||
echo str[i]</syntaxhighlight> |
|||
===Thread Pools=== |
|||
Compile with <code>nim --threads:on c concurrent</code>: |
|||
<syntaxhighlight lang="nim">import threadpool |
|||
const str = ["Enjoy", "Rosetta", "Code"] |
|||
proc f(i: int) {.thread.} = |
|||
echo str[i] |
|||
for i in 0..str.high: |
|||
spawn f(i) |
|||
sync()</syntaxhighlight> |
|||
=={{header|Objeck}}== |
|||
<syntaxhighlight lang="objeck"> |
|||
bundle Default { |
|||
class MyThread from Thread { |
|||
New(name : String) { |
|||
Parent(name); |
|||
} |
|||
method : public : Run(param : Base) ~ Nil { |
|||
string := param->As(String); |
|||
string->PrintLine(); |
|||
} |
|||
} |
|||
class Concurrent { |
|||
New() { |
|||
} |
|||
function : Main(args : System.String[]) ~ Nil { |
|||
t0 := MyThread->New("t0"); |
|||
t1 := MyThread->New("t1"); |
|||
t2 := MyThread->New("t2"); |
|||
t0->Execute("Enjoy"->As(Base)); |
|||
t1->Execute("Rosetta"->As(Base)); |
|||
t2->Execute("Code"->As(Base)); |
|||
} |
|||
} |
|||
} |
|||
</syntaxhighlight> |
|||
=={{header|OCaml}}== |
|||
<syntaxhighlight lang="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 () = |
|||
Random.self_init (); |
|||
List.iter (Thread.join) threads</syntaxhighlight> |
|||
=={{header|Oforth}}== |
|||
Oforth uses tasks to implement concurrent computing. A task is scheduled using #& on a function, method, block, ... |
|||
<syntaxhighlight lang="oforth">#[ "Enjoy" println ] & |
|||
#[ "Rosetta" println ] & |
|||
#[ "Code" println ] &</syntaxhighlight> |
|||
mapParallel method can be used to map a runnable on each element of a collection and returns a collection of results. Here, we println the string and return string size. |
|||
<syntaxhighlight lang="oforth">[ "Enjoy", "Rosetta", "Code" ] mapParallel(#[ dup . size ])</syntaxhighlight> |
|||
=={{header|Ol}}== |
|||
<syntaxhighlight lang="scheme"> |
|||
(import (otus random!)) |
|||
(for-each (lambda (str) |
|||
(define timeout (rand! 999)) |
|||
(async (lambda () |
|||
(sleep timeout) |
|||
(print str)))) |
|||
'("Enjoy" "Rosetta" "Code")) |
|||
</syntaxhighlight> |
|||
{{Out}} |
|||
<pre>Code |
|||
Enjoy |
|||
Rosetta |
|||
</pre> |
|||
=={{header|ooRexx}}== |
|||
<syntaxhighlight lang="oorexx"> |
|||
-- this will launch 3 threads, with each thread given a message to print out. |
|||
-- I've added a stoplight to make each thread wait until given a go signal, |
|||
-- plus some sleeps to give the threads a chance to randomize the execution |
|||
-- order a little. |
|||
launcher = .launcher~new |
|||
launcher~launch |
|||
::class launcher |
|||
-- the launcher method. Guarded is the default, but let's make this |
|||
-- explicit here |
|||
::method launch guarded |
|||
runner1 = .runner~new(self, "Enjoy") |
|||
runner2 = .runner~new(self, "Rosetta") |
|||
runner3 = .runner~new(self, "Code") |
|||
-- let's give the threads a chance to settle in to the |
|||
-- starting line |
|||
call syssleep 1 |
|||
guard off -- release the launcher lock. This is the starter's gun |
|||
-- this is a guarded method that the runners will call. They |
|||
-- will block until the launch method releases the object guard |
|||
::method block guarded |
|||
::class runner |
|||
::method init |
|||
use arg launcher, text |
|||
reply -- this creates the new thread |
|||
call syssleep .5 -- try to mix things up by sleeping |
|||
launcher~block -- wait for the go signal |
|||
call syssleep .5 -- add another sleep here |
|||
say text |
|||
</syntaxhighlight> |
|||
=={{header|Oz}}== |
|||
The randomness comes from the unpredictability of thread scheduling (this is how I understand this exercise). |
|||
<syntaxhighlight lang="oz">for Msg in ["Enjoy" "Rosetta" "Code"] do |
|||
thread |
|||
{System.showInfo Msg} |
|||
end |
|||
end |
|||
</syntaxhighlight> |
|||
=={{header|PARI/GP}}== |
|||
Here is a GP implementation using the [http://pari.math.u-bordeaux.fr/cgi-bin/gitweb.cgi?p=pari.git;a=tree;h=refs/heads/bill-mt;hb=refs/heads/bill-mt bill-mt] branch: |
|||
<syntaxhighlight lang="parigp">inline(func); |
|||
func(n)=print(["Enjoy","Rosetta","Code"][n]); |
|||
parapply(func,[1..3]);</syntaxhighlight> |
|||
This is a PARI implementation which uses <code>fork()</code> internally. Note that the [[#C|C]] solutions can be used instead if desired; this program demonstrates the native PARI capabilities instead. |
|||
For serious concurrency, see Appendix B of the User's Guide to the PARI Library which discusses a solution using [[wp:Thread-local storage|tls]] on [[wp:POSIX Threads|pthreads]]. (There are nontrivial issues with using PARI in this environment, do not attempt to blindly implement a [[#C|C]] solution.) |
|||
<syntaxhighlight lang="c">void |
|||
foo() |
|||
{ |
|||
if (pari_daemon()) { |
|||
// Original |
|||
if (pari_daemon()) { |
|||
// Original |
|||
pari_printf("Enjoy\n"); |
|||
} else { |
|||
// Daemon #2 |
|||
pari_printf("Code\n"); |
|||
} |
|||
} else { |
|||
// Daemon #1 |
|||
pari_printf("Rosetta\n"); |
|||
} |
|||
}</syntaxhighlight> |
|||
See also [http://pari.math.u-bordeaux1.fr/Events/PARI2012/talks/pareval.pdf Bill Allombert's slides on parallel programming in GP]. |
|||
=={{header|Pascal}}== |
|||
{{trans|Delphi}} modified for linux. Using simple running thread-counter to circumvent WaitForMultipleObjects.<BR> |
|||
Output of difference of sleep time and true sleep time ( running with 0..1999 threads you see once a while 1) |
|||
<syntaxhighlight lang="pascal">program ConcurrentComputing; |
|||
{$IFdef FPC} |
|||
{$MODE DELPHI} |
|||
{$ELSE} |
|||
{$APPTYPE CONSOLE} |
|||
{$ENDIF} |
|||
uses |
|||
{$IFDEF UNIX} |
|||
cthreads, |
|||
{$ENDIF} |
|||
SysUtils, Classes; |
|||
type |
|||
TRandomThread = class(TThread) |
|||
private |
|||
FString: string; |
|||
T0 : Uint64; |
|||
protected |
|||
procedure Execute; override; |
|||
public |
|||
constructor Create(const aString: string); overload; |
|||
end; |
|||
const |
|||
MyStrings: array[0..2] of String = ('Enjoy ','Rosetta ','Code '); |
|||
var |
|||
gblRunThdCnt : LongWord = 0; |
|||
constructor TRandomThread.Create(const aString: string); |
|||
begin |
|||
inherited Create(False); |
|||
FreeOnTerminate := True; |
|||
FString := aString; |
|||
interlockedincrement(gblRunThdCnt); |
|||
end; |
|||
procedure TRandomThread.Execute; |
|||
var |
|||
i : NativeInt; |
|||
begin |
|||
i := Random(300); |
|||
T0 := GettickCount64; |
|||
Sleep(i); |
|||
//output of difference in time |
|||
Writeln(FString,i:4,GettickCount64-T0 -i:2); |
|||
interlockeddecrement(gblRunThdCnt); |
|||
end; |
|||
var |
|||
lThreadArray: Array[0..9] of THandle; |
|||
i : NativeInt; |
|||
begin |
|||
Randomize; |
|||
gblRunThdCnt := 0; |
|||
For i := low(lThreadArray) to High(lThreadArray) do |
|||
lThreadArray[i] := TRandomThread.Create(Format('%9s %4d',[myStrings[Random(3)],i])).Handle; |
|||
while gblRunThdCnt > 0 do |
|||
sleep(125); |
|||
end.</syntaxhighlight> |
|||
{{out}} |
|||
<pre> |
|||
Enjoy 4 16 0 |
|||
Code 0 22 0 |
|||
Code 1 32 0 |
|||
Rosetta 7 117 0 |
|||
Enjoy 2 137 0 |
|||
Code 6 214 0 |
|||
Code 5 252 0 |
|||
Enjoy 3 299 0</pre> |
|||
=={{header|Perl}}== |
|||
<syntaxhighlight lang="perl">use threads; |
|||
use Time::HiRes qw(sleep); |
|||
$_->join for map { |
|||
threads->create(sub { |
|||
sleep rand; |
|||
print shift, "\n"; |
|||
}, $_) |
|||
} qw(Enjoy Rosetta Code);</syntaxhighlight> |
|||
Or using coroutines provided by {{libheader|Coro}} |
|||
<syntaxhighlight lang="perl">use feature qw( say ); |
|||
use Coro; |
|||
use Coro::Timer qw( sleep ); |
|||
$_->join for map { |
|||
async { |
|||
sleep rand; |
|||
say @_; |
|||
} $_ |
|||
} qw( Enjoy Rosetta Code ); |
|||
</syntaxhighlight> |
|||
=={{header|Phix}}== |
|||
Without the sleep it is almost always Enjoy Rosetta Code, because create_thread() is more costly than echo(), as the former has to create a new call stack etc.<br> |
|||
The lock prevents the displays from mangling each other. |
|||
<!--<syntaxhighlight lang="phix">(notonline)--> |
|||
<span style="color: #008080;">without</span> <span style="color: #008080;">js</span> <span style="color: #000080;font-style:italic;">-- (threads)</span> |
|||
<span style="color: #008080;">procedure</span> <span style="color: #000000;">echo</span><span style="color: #0000FF;">(</span><span style="color: #004080;">string</span> <span style="color: #000000;">s</span><span style="color: #0000FF;">)</span> |
|||
<span style="color: #7060A8;">sleep</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">rand</span><span style="color: #0000FF;">(</span><span style="color: #000000;">100</span><span style="color: #0000FF;">)/</span><span style="color: #000000;">100</span><span style="color: #0000FF;">)</span> |
|||
<span style="color: #7060A8;">enter_cs</span><span style="color: #0000FF;">()</span> |
|||
<span style="color: #7060A8;">puts</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">s</span><span style="color: #0000FF;">)</span> |
|||
<span style="color: #7060A8;">puts</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">'\n'</span><span style="color: #0000FF;">)</span> |
|||
<span style="color: #7060A8;">leave_cs</span><span style="color: #0000FF;">()</span> |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">procedure</span> |
|||
<span style="color: #008080;">constant</span> <span style="color: #000000;">threads</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">create_thread</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">routine_id</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"echo"</span><span style="color: #0000FF;">),{</span><span style="color: #008000;">"Enjoy"</span><span style="color: #0000FF;">}),</span> |
|||
threading.Timer(random.random(), echo, ("Enjoy",)).start() |
|||
<span style="color: #000000;">create_thread</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">routine_id</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"echo"</span><span style="color: #0000FF;">),{</span><span style="color: #008000;">"Rosetta"</span><span style="color: #0000FF;">}),</span> |
|||
threading.Timer(random.random(), echo, ("Rosetta",)).start() |
|||
<span style="color: #000000;">create_thread</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">routine_id</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"echo"</span><span style="color: #0000FF;">),{</span><span style="color: #008000;">"Code"</span><span style="color: #0000FF;">})}</span> |
|||
threading.Timer(random.random(), echo, ("Code",)).start() |
|||
<span style="color: #000000;">wait_thread</span><span style="color: #0000FF;">(</span><span style="color: #000000;">threads</span><span style="color: #0000FF;">)</span> |
|||
<span style="color: #7060A8;">puts</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"done"</span><span style="color: #0000FF;">)</span> |
|||
<span style="color: #0000FF;">{}</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">wait_key</span><span style="color: #0000FF;">()</span> |
|||
<!--</syntaxhighlight>--> |
|||
=={{header|PicoLisp}}== |
|||
===Using background tasks=== |
|||
<syntaxhighlight lang="picolisp">(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</syntaxhighlight> |
|||
===Using child processes=== |
|||
<syntaxhighlight lang="picolisp">(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</syntaxhighlight> |
|||
=={{header|Pike}}== |
|||
Using POSIX threads: |
|||
<syntaxhighlight lang="pike">int main() { |
|||
// Start threads and wait for them to finish |
|||
({ |
|||
Thread.Thread(write, "Enjoy\n"), |
|||
Thread.Thread(write, "Rosetta\n"), |
|||
Thread.Thread(write, "Code\n") |
|||
})->wait(); |
|||
// Exit program |
|||
exit(0); |
|||
}</syntaxhighlight> |
|||
Output: |
|||
Enjoy |
|||
Rosetta |
|||
Code |
|||
Using Pike's backend: |
|||
<syntaxhighlight lang="pike">int main(int argc, array argv) |
|||
{ |
|||
call_out(write, random(1.0), "Enjoy\n"); |
|||
call_out(write, random(1.0), "Rosetta\n"); |
|||
call_out(write, random(1.0), "Code\n"); |
|||
call_out(exit, 1, 0); |
|||
return -1; // return -1 starts the backend which makes Pike run until exit() is called. |
|||
}</syntaxhighlight> |
|||
Output: |
|||
Rosetta |
|||
Code |
|||
Enjoy |
|||
=={{header|PowerShell}}== |
|||
Using Background Jobs: |
|||
<syntaxhighlight lang="powershell">$Strings = "Enjoy","Rosetta","Code" |
|||
$SB = {param($String)Write-Output $String} |
|||
foreach($String in $Strings) { |
|||
Start-Job -ScriptBlock $SB -ArgumentList $String | Out-Null |
|||
} |
|||
Get-Job | Wait-Job | Receive-Job |
|||
Get-Job | Remove-Job</syntaxhighlight> |
|||
Using .NET Runspaces: |
|||
<syntaxhighlight lang="powershell">$Strings = "Enjoy","Rosetta","Code" |
|||
$SB = {param($String)Write-Output $String} |
|||
$Pool = [RunspaceFactory]::CreateRunspacePool(1, 3) |
|||
$Pool.ApartmentState = "STA" |
|||
$Pool.Open() |
|||
foreach ($String in $Strings) { |
|||
$Pipeline = [System.Management.Automation.PowerShell]::create() |
|||
$Pipeline.RunspacePool = $Pool |
|||
[void]$Pipeline.AddScript($SB).AddArgument($String) |
|||
$AsyncHandle = $Pipeline.BeginInvoke() |
|||
$Pipeline.EndInvoke($AsyncHandle) |
|||
$Pipeline.Dispose() |
|||
} |
|||
$Pool.Close()</syntaxhighlight> |
|||
=={{header|Prolog}}== |
|||
This example works in SWI-Prolog. It may work in other Prolog implementations too. |
|||
Create a separate thread for each word. Join the threads to make sure they complete before the program exits. |
|||
<syntaxhighlight lang="prolog">main :- |
|||
thread_create(say("Enjoy"),A,[]), |
|||
thread_create(say("Rosetta"),B,[]), |
|||
thread_create(say("Code"),C,[]), |
|||
thread_join(A,_), |
|||
thread_join(B,_), |
|||
thread_join(C,_). |
|||
say(Message) :- |
|||
Delay is random_float, |
|||
sleep(Delay), |
|||
writeln(Message).</syntaxhighlight> |
|||
=={{header|PureBasic}}== |
|||
<syntaxhighlight lang="purebasic">Global mutex = CreateMutex() |
|||
Procedure Printer(*str) |
|||
LockMutex(mutex) |
|||
PrintN( PeekS(*str) ) |
|||
UnlockMutex(mutex) |
|||
EndProcedure |
|||
If OpenConsole() |
|||
LockMutex(mutex) |
|||
thread1 = CreateThread(@Printer(), @"Enjoy") |
|||
thread2 = CreateThread(@Printer(), @"Rosetta") |
|||
thread3 = CreateThread(@Printer(), @"Code") |
|||
UnlockMutex(mutex) |
|||
WaitThread(thread1) |
|||
WaitThread(thread2) |
|||
WaitThread(thread3) |
|||
Print(#CRLF$ + #CRLF$ + "Press ENTER to exit") |
|||
Input() |
|||
CloseConsole() |
|||
EndIf |
|||
FreeMutex(mutex)</syntaxhighlight> |
|||
=={{header|Python}}== |
|||
{{works with|Python|3.7}} |
|||
Using asyncio module (I know almost nothing about it, so feel free to improve it :-)): |
|||
<syntaxhighlight lang="python">import asyncio |
|||
async def print_(string: str) -> None: |
|||
print(string) |
|||
async def main(): |
|||
strings = ['Enjoy', 'Rosetta', 'Code'] |
|||
coroutines = map(print_, strings) |
|||
await asyncio.gather(*coroutines) |
|||
if __name__ == '__main__': |
|||
asyncio.run(main())</syntaxhighlight> |
|||
{{works with|Python|3.2}} |
|||
Using the new to Python 3.2 [http://docs.python.org/release/3.2/library/concurrent.futures.html concurrent.futures library] and choosing to use processes over threads; the example will use up to as many processes as your machine has cores. This doesn't however guarantee an order of sub-process results. |
|||
<syntaxhighlight lang="python">Python 3.2 (r32:88445, Feb 20 2011, 21:30:00) [MSC v.1500 64 bit (AMD64)] on win 32 |
|||
Type "help", "copyright", "credits" or "license" for more information. |
|||
>>> from concurrent import futures |
|||
>>> with futures.ProcessPoolExecutor() as executor: |
|||
... _ = list(executor.map(print, 'Enjoy Rosetta Code'.split())) |
|||
... |
|||
Enjoy |
|||
Rosetta |
|||
Code |
|||
>>></syntaxhighlight> |
|||
{{works with|Python|2.5}} |
|||
==[[Raven]]== |
|||
[[Category:Raven]] |
|||
<syntaxhighlight lang="python">import threading |
|||
[ 'Enjoy' 'Rosetta' 'Code' ] as $words |
|||
import random |
|||
def echo(text): |
|||
thread talker |
|||
print(text) |
|||
$words pop "%s\n" |
|||
repeat dup print |
|||
500 choose ms |
|||
threading.Timer(random.random(), echo, ("Enjoy",)).start() |
|||
talker as a |
|||
threading.Timer(random.random(), echo, ("Rosetta",)).start() |
|||
talker as b |
|||
threading.Timer(random.random(), echo, ("Code",)).start()</syntaxhighlight> |
|||
talker as c |
|||
Or, by using a for loop to start one thread per list entry, where our list is our set of source strings: |
|||
==[[Ruby]]== |
|||
[[Category:Ruby]] |
|||
<syntaxhighlight lang="python">import threading |
|||
%w{Enjoy Rosetta Code}.map{ |
|||
import random |
|||
|x| |
|||
Thread.new{ |
|||
sleep rand |
|||
puts x |
|||
} |
|||
}.each{ |
|||
|t| |
|||
t.join |
|||
} |
|||
def echo(text): |
|||
==[[Tcl]]== |
|||
print(text) |
|||
[[Category:Tcl]] |
|||
for text in ["Enjoy", "Rosetta", "Code"]: |
|||
threading.Timer(random.random(), echo, (text,)).start()</syntaxhighlight> |
|||
=== threading.Thread === |
|||
<syntaxhighlight lang="python">import random, sys, time |
|||
import threading |
|||
lock = threading.Lock() |
|||
def echo(s): |
|||
time.sleep(1e-2*random.random()) |
|||
# use `.write()` with lock due to `print` prints empty lines occasionally |
|||
with lock: |
|||
sys.stdout.write(s) |
|||
sys.stdout.write('\n') |
|||
for line in 'Enjoy Rosetta Code'.split(): |
|||
threading.Thread(target=echo, args=(line,)).start()</syntaxhighlight> |
|||
=== multiprocessing === |
|||
{{works with|Python|2.6}} |
|||
<syntaxhighlight lang="python">from __future__ import print_function |
|||
from multiprocessing import Pool |
|||
def main(): |
|||
p = Pool() |
|||
p.map(print, 'Enjoy Rosetta Code'.split()) |
|||
if __name__=="__main__": |
|||
main()</syntaxhighlight> |
|||
=== twisted === |
|||
<syntaxhighlight lang="python">import random |
|||
from twisted.internet import reactor, task, defer |
|||
from twisted.python.util import println |
|||
delay = lambda: 1e-4*random.random() |
|||
d = defer.DeferredList([task.deferLater(reactor, delay(), println, line) |
|||
for line in 'Enjoy Rosetta Code'.split()]) |
|||
d.addBoth(lambda _: reactor.stop()) |
|||
reactor.run()</syntaxhighlight> |
|||
=== gevent === |
|||
<syntaxhighlight lang="python">from __future__ import print_function |
|||
import random |
|||
import gevent |
|||
delay = lambda: 1e-4*random.random() |
|||
gevent.joinall([gevent.spawn_later(delay(), print, line) |
|||
for line in 'Enjoy Rosetta Code'.split()])</syntaxhighlight> |
|||
=={{header|Racket}}== |
|||
Threads provide a simple API for concurrent programming. |
|||
<syntaxhighlight lang="racket"> |
|||
#lang racket |
|||
(for ([str '("Enjoy" "Rosetta" "Code")]) |
|||
(thread (λ () (displayln str)))) |
|||
</syntaxhighlight> |
|||
In addition to "thread" which is implemented as green threads (useful for IO etc), Racket has "futures" and "places" which are similar tools for using multiple OS cores. |
|||
=={{header|Raku}}== |
|||
(formerly Perl 6) |
|||
{{works with|Rakudo|2018.9}} |
|||
<syntaxhighlight lang="raku" line>my @words = <Enjoy Rosetta Code>; |
|||
@words.race(:batch(1)).map: { sleep rand; say $_ };</syntaxhighlight> |
|||
{{out}} |
|||
<pre>Code |
|||
Rosetta |
|||
Enjoy</pre> |
|||
=={{header|Raven}}== |
|||
<syntaxhighlight 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</syntaxhighlight> |
|||
=={{header|Rhope}}== |
|||
{{works with|Rhope|alpha 1}} |
|||
<syntaxhighlight lang="rhope">Main(0,0) |
|||
|: |
|||
Print["Enjoy"] |
|||
Print["Rosetta"] |
|||
Print["Code"] |
|||
:|</syntaxhighlight> |
|||
In Rhope, expressions with no shared dependencies run in parallel by default. |
|||
=={{header|Ruby}}== |
|||
<syntaxhighlight lang="ruby">%w{Enjoy Rosetta Code}.map do |x| |
|||
Thread.new do |
|||
sleep rand |
|||
puts x |
|||
end |
|||
end.each do |t| |
|||
t.join |
|||
end</syntaxhighlight> |
|||
=={{header|Rust}}== |
|||
{{libheader|rand}} |
|||
<syntaxhighlight lang="rust">extern crate rand; // not needed for recent versions |
|||
use std::thread; |
|||
use rand::thread_rng; |
|||
use rand::distributions::{Range, IndependentSample}; |
|||
fn main() { |
|||
let mut rng = thread_rng(); |
|||
let rng_range = Range::new(0u32, 100); |
|||
for word in "Enjoy Rosetta Code".split_whitespace() { |
|||
let snooze_time = rng_range.ind_sample(&mut rng); |
|||
let local_word = word.to_owned(); |
|||
std::thread::spawn(move || { |
|||
thread::sleep_ms(snooze_time); |
|||
println!("{}", local_word); |
|||
}); |
|||
} |
|||
thread::sleep_ms(1000); |
|||
}</syntaxhighlight> |
|||
=={{header|Scala}}== |
|||
<syntaxhighlight lang="scala">import scala.actors.Futures |
|||
List("Enjoy", "Rosetta", "Code").map { x => |
|||
Futures.future { |
|||
Thread.sleep((Math.random * 1000).toInt) |
|||
println(x) |
|||
} |
|||
}.foreach(_())</syntaxhighlight> |
|||
=={{header|Scheme}}== |
|||
<syntaxhighlight lang="scheme">(parallel-execute (lambda () (print "Enjoy")) |
|||
(lambda () (print "Rosetta")) |
|||
(lambda () (print "Code")))</syntaxhighlight> |
|||
If your implementation doesn't provide parallel-execute, it can be implemented with [https://srfi.schemers.org/srfi-18/srfi-18.html SRFI-18]. |
|||
<syntaxhighlight lang="scheme">(import (srfi 18)) |
|||
(define (parallel-execute . thunks) |
|||
(let ((threads (map make-thread thunks))) |
|||
(for-each thread-start! threads) |
|||
(for-each thread-join! threads)))</syntaxhighlight> |
|||
=={{header|Sidef}}== |
|||
A very basic threading support is provided by the '''Block.fork()''' method: |
|||
<syntaxhighlight lang="ruby">var a = <Enjoy Rosetta Code> |
|||
a.map{|str| |
|||
{ Sys.sleep(1.rand) |
|||
say str |
|||
}.fork |
|||
}.map{|thr| thr.wait }</syntaxhighlight> |
|||
{{out}} |
|||
<pre> |
|||
Enjoy |
|||
Code |
|||
Rosetta |
|||
</pre> |
|||
=={{header|Slope}}== |
|||
<syntaxhighlight lang="slope">(coeval |
|||
(display "Enjoy") |
|||
(display "Rosetta") |
|||
(display "Code"))</syntaxhighlight> |
|||
=={{header|Swift}}== |
|||
Using Grand Central Dispatch with concurrent queues. |
|||
<syntaxhighlight lang="swift">import Foundation |
|||
let myList = ["Enjoy", "Rosetta", "Code"] |
|||
for word in myList { |
|||
dispatch_async(dispatch_get_global_queue(0, 0)) { |
|||
NSLog(word) |
|||
} |
|||
} |
|||
dispatch_main()</syntaxhighlight> |
|||
{{out}} |
|||
<pre> |
|||
2015-02-05 10:15:01.831 rosettaconcurrency[1917:37905] Code |
|||
2015-02-05 10:15:01.831 rosettaconcurrency[1917:37902] Enjoy |
|||
2015-02-05 10:15:01.831 rosettaconcurrency[1917:37904] Rosetta |
|||
</pre> |
|||
=={{header|Standard ML}}== |
|||
Works with PolyML |
|||
<syntaxhighlight lang="standard ml">structure TTd = Thread.Thread ; |
|||
structure TTm = Thread.Mutex ; |
|||
val threadedStringList = fn tasks:string list => |
|||
let |
|||
val mx = TTm.mutex () ; |
|||
val taskstore = ref tasks ; |
|||
fun makeFastRand () = Real.rem (Time.toReal (Time.now ()),1.0) |
|||
val doTask = fn () => |
|||
let |
|||
val mytask : string ref = ref "" ; |
|||
in |
|||
( TTm.lock mx ; mytask := hd ( !taskstore ) ; taskstore:= tl (!taskstore) ; TTm.unlock mx ; |
|||
Posix.Process.sleep (Time.fromReal (makeFastRand ())) ; |
|||
TTm.lock mx ; print ( !mytask ^ "\n") ; TTm.unlock mx ; |
|||
TTd.exit () |
|||
) |
|||
end |
|||
in |
|||
List.tabulate ( length tasks , fn i => TTd.fork (doTask , []) ) |
|||
end ; |
|||
</syntaxhighlight> |
|||
call |
|||
threadedStringList [ "Enjoy","Rosetta","Code" ]; |
|||
Rosetta |
|||
Code |
|||
Enjoy |
|||
=={{header|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: |
||
<syntaxhighlight lang="tcl">after [expr int(1000*rand())] {puts "Enjoy"} |
|||
after [expr int(1000*rand())] {puts "Rosetta"} |
|||
after [expr int(1000*rand())] {puts "Code"}</syntaxhighlight> |
|||
will execute each line after a randomly chosen number (0...1000) of milliseconds. |
will execute each line after a randomly chosen number (0...1000) of milliseconds. |
||
Line 184: | Line 2,085: | ||
A step towards "undefined" would be to use <tt>after idle</tt>, which is Tcl for "do this whenever you get around to it". Thus: |
A step towards "undefined" would be to use <tt>after idle</tt>, which is Tcl for "do this whenever you get around to it". Thus: |
||
<syntaxhighlight lang="tcl">after idle {puts "Enjoy"} |
|||
after idle {puts "Rosetta"} |
|||
after idle {puts "Code"}</syntaxhighlight> |
|||
(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: |
|||
<syntaxhighlight lang="tcl">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</syntaxhighlight> |
|||
=={{header|UnixPipes}}== |
|||
<syntaxhighlight lang="bash">(echo "Enjoy" & echo "Rosetta"& echo "Code"&)</syntaxhighlight> |
|||
=={{header|VBA}}== |
|||
Three tasks scheduled for the same time with OnTime. The last scheduled task gets executed first. |
|||
<syntaxhighlight lang="vb">Private Sub Enjoy() |
|||
Debug.Print "Enjoy" |
|||
End Sub |
|||
Private Sub Rosetta() |
|||
Debug.Print "Rosetta" |
|||
End Sub |
|||
Private Sub Code() |
|||
Debug.Print "Code" |
|||
End Sub |
|||
Public Sub concurrent() |
|||
when = Now + TimeValue("00:00:01") |
|||
Application.OnTime when, "Enjoy" |
|||
Application.OnTime when, "Rosetta" |
|||
Application.OnTime when, "Code" |
|||
End Sub</syntaxhighlight> |
|||
=={{header|Visual Basic .NET}}== |
|||
<syntaxhighlight lang="vbnet">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</syntaxhighlight> |
|||
===Alternative version=== |
|||
[https://tio.run/##TY9PC8IwDMXv@xRhpw60oODFm@gEQUWs4Llbg6t0zWjrn3362bmBvssjCfnl5VlMS3LYdbu6IRc8iNYHrPmlciiVtrfkQOphEAabJRC10TU4q2Dl4YgvOEurqGbZdyYeBRyktmPZ6ySdNAYN35LLZVmxNLd3auFMHkOQsCaFKReN0YGlkGaTHsL8D9BrCMSFQWxYPM6P@A5svsgyWEaC9WSQX50OuNcW/7fzmDQCh8ZYJL0PL3XdBw Try It Online!] |
|||
<syntaxhighlight lang="vbnet">Imports System.Threading |
|||
Module Module1 |
|||
Dim rnd As New Random() |
|||
Sub Main() |
|||
Parallel.ForEach("Enjoy Rosetta Code".Split(" "), Sub(s) |
|||
Thread.Sleep(rnd.Next(25)) : Console.WriteLine(s) |
|||
End Sub) |
|||
End Sub |
|||
End Module</syntaxhighlight> |
|||
{{out}} |
|||
<pre>Rosetta |
|||
Enjoy |
|||
Code</pre> |
|||
=={{header|V (Vlang)}}== |
|||
===Porting of Go code=== |
|||
<syntaxhighlight lang="go">import time |
|||
import rand |
|||
import rand.pcg32 |
|||
import rand.seed |
|||
fn main() { |
|||
words := ['Enjoy', 'Rosetta', 'Code'] |
|||
seed_u64 := u64(time.now().unix_time_milli()) |
|||
q := chan string{} |
|||
for i, w in words { |
|||
go fn (q chan string, w string, seed_u64 u64) { |
|||
mut rng := pcg32.PCG32RNG{} |
|||
time_seed := seed.time_seed_array(2) |
|||
seed_arr := [u32(seed_u64), u32(seed_u64 >> 32), time_seed[0], time_seed[1]] |
|||
rng.seed(seed_arr) |
|||
time.sleep(time.Duration(rng.i64n(1_000_000_000))) |
|||
q <- w |
|||
}(q, w, seed_u64 + u64(i)) |
|||
} |
|||
for _ in 0 .. words.len { |
|||
println(<-q) |
|||
} |
|||
}</syntaxhighlight> |
|||
===Vlang Idiomatic version=== |
|||
<syntaxhighlight lang="go">import time |
|||
import rand |
|||
import rand.pcg32 |
|||
import rand.seed |
|||
fn main() { |
|||
words := ['Enjoy', 'Rosetta', 'Code'] |
|||
mut threads := []thread{} // mutable array to hold the id of the thread |
|||
for w in words { |
|||
threads << go fn (w string) { // record the thread |
|||
mut rng := pcg32.PCG32RNG{} |
|||
time_seed := seed.time_seed_array(4) // the time derived array to seed the random generator |
|||
rng.seed(time_seed) |
|||
time.sleep(time.Duration(rng.i64n(1_000_000_000))) |
|||
println(w) |
|||
}(w) |
|||
} |
|||
threads.wait() // join the thread waiting. wait() is defined for threads and arrays of threads |
|||
}</syntaxhighlight> |
|||
{{out}}<pre>Code |
|||
Rosetta |
|||
Enjoy |
|||
Rosetta |
|||
Enjoy |
|||
Code</pre> |
|||
=={{header|Wren}}== |
|||
<syntaxhighlight lang="wren">import "random" for Random |
|||
var words = ["Enjoy", "Rosetta", "Code"] |
|||
var rand = Random.new() |
|||
for (h in 1..3) { |
|||
var fibers = List.filled(3, null) |
|||
for (i in 0..2) fibers[i] = Fiber.new { System.print(words[i]) } |
|||
var called = List.filled(3, false) |
|||
var j = 0 |
|||
while (j < 3) { |
|||
var k = rand.int(3) |
|||
if (!called[k]) { |
|||
fibers[k].call() |
|||
called[k] = true |
|||
j = j + 1 |
|||
} |
|||
} |
|||
System.print() |
|||
}</syntaxhighlight> |
|||
{{out}} |
|||
Sample run: |
|||
<pre> |
|||
Enjoy |
|||
Code |
|||
Rosetta |
|||
Code |
|||
Enjoy |
|||
Rosetta |
|||
Rosetta |
|||
Enjoy |
|||
Code |
|||
</pre> |
|||
=={{header|XPL0}}== |
|||
Works on Raspberry Pi using XPL0 version 3.2. Processes actually execute |
|||
simultaneously, one per CPU core (beyond single-core RPi-1). Lock is |
|||
necessary to enable one line to finish printing before another line starts. |
|||
<syntaxhighlight lang="xpl0">int Key, Process; |
|||
[Key:= SharedMem(4); \allocate 4 bytes of memory common to all processes |
|||
Process:= Fork(2); \start 2 child processes |
|||
case Process of |
|||
0: [Lock(Key); Text(0, "Enjoy"); CrLf(0); Unlock(Key)]; \parent process |
|||
1: [Lock(Key); Text(0, "Rosetta"); CrLf(0); Unlock(Key)]; \child process |
|||
2: [Lock(Key); Text(0, "Code"); CrLf(0); Unlock(Key)] \child process |
|||
other [Lock(Key); Text(0, "Error"); CrLf(0); Unlock(Key)]; |
|||
Join(Process); \wait for all child processes to finish |
|||
]</syntaxhighlight> |
|||
{{out}} |
|||
<pre> |
|||
Code |
|||
Enjoy |
|||
Rosetta |
|||
</pre> |
|||
=={{header|zkl}}== |
|||
<syntaxhighlight lang="zkl">fcn{println("Enjoy")}.launch(); // thread |
|||
fcn{println("Rosetta")}.strand(); // co-op thread |
|||
fcn{println("Code")}.future(); // another thread type</syntaxhighlight> |
|||
{{out}} |
|||
<pre> |
|||
Rosetta |
|||
Code |
|||
Enjoy |
|||
</pre> |
|||
{{omit from|AWK}} |
|||
(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). |
|||
{{omit from|bc}} |
|||
{{omit from|Brlcad}} |
|||
{{omit from|dc}} |
|||
{{omit from|GUISS}} |
|||
{{omit from|Lilypond}} |
|||
{{omit from|Maxima}} |
|||
{{Omit From|Metafont}} |
|||
{{omit from|Openscad}} |
|||
{{omit from|TI-83 BASIC|Does not have concurrency or background processes.}} |
|||
{{omit from|TI-89 BASIC|Does not have concurrency or background processes.}} |
|||
{{omit from|TPP}} |
|||
{{omit from|Vim Script}} |
|||
{{omit from|ZX Spectrum Basic}} |
|||
{{omit from|Axe}} |
Latest revision as of 16:30, 20 November 2023
You are encouraged to solve this task according to the task description, using any language you may know.
- Task
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
with Ada.Text_IO, Ada.Numerics.Float_Random;
procedure Concurrent_Hello is
type Messages is (Enjoy, Rosetta, Code);
task type Writer (Message : Messages);
task body Writer is
Seed : Ada.Numerics.Float_Random.Generator;
begin
Ada.Numerics.Float_Random.Reset (Seed); -- time-dependent, see ARM A.5.2
delay Duration (Ada.Numerics.Float_Random.Random (Seed));
Ada.Text_IO.Put_Line (Messages'Image(Message));
end Writer;
Taks: array(Messages) of access Writer -- 3 Writer tasks will immediately run
:= (new Writer(Enjoy), new Writer(Rosetta), new Writer(Code));
begin
null; -- the "environment task" doesn't need to do anything
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 (see ARM A.5.2).
ALGOL 68
main:(
PROC echo = (STRING string)VOID:
printf(($gl$,string));
PAR(
echo("Enjoy"),
echo("Rosetta"),
echo("Code")
)
)
APL
Dyalog APL supports the &
operator, which runs a function on its own thread.
{⎕←⍵}&¨'Enjoy' 'Rosetta' 'Code'
- Output:
(Example)
Enjoy Code Rosetta
Astro
let words = ["Enjoy", "Rosetta", "Code"]
for word in words:
(word) |> async (w) =>
sleep(random())
print(w)
BASIC
BaCon
BaCon is a BASIC-to-C compiler. Assuming GCC compiler in this demonstration. Based on the C OpenMP source.
' Concurrent computing using the OpenMP extension in GCC. Requires BaCon 3.6 or higher.
' Specify compiler flag
PRAGMA OPTIONS -fopenmp
' Sepcify linker flag
PRAGMA LDFLAGS -lgomp
' Declare array with text
DECLARE str$[] = { "Enjoy", "Rosetta", "Code" }
' Indicate MP optimization for FOR loop
PRAGMA omp parallel for num_threads(3)
' The actual FOR loop
FOR i = 0 TO 2
PRINT str$[i]
NEXT
- Output:
prompt$ bacon concurrent-computing Converting 'concurrent-computing.bac'... done, 11 lines were processed in 0.002 seconds. Compiling 'concurrent-computing.bac'... cc -fopenmp -c concurrent-computing.bac.c cc -o concurrent-computing concurrent-computing.bac.o -lbacon -lm -lgomp Done, program 'concurrent-computing' ready. prompt$ ./concurrent-computing Code Enjoy Rosetta
BBC BASIC
The BBC BASIC interpreter is single-threaded so the only way of achieving 'concurrency' (short of using assembler code) is to use timer events:
INSTALL @lib$+"TIMERLIB"
tID1% = FN_ontimer(100, PROCtask1, 1)
tID2% = FN_ontimer(100, PROCtask2, 1)
tID3% = FN_ontimer(100, PROCtask3, 1)
ON ERROR PRINT REPORT$ : PROCcleanup : END
ON CLOSE PROCcleanup : QUIT
REPEAT
WAIT 0
UNTIL FALSE
END
DEF PROCtask1
PRINT "Enjoy"
ENDPROC
DEF PROCtask2
PRINT "Rosetta"
ENDPROC
DEF PROCtask3
PRINT "Code"
ENDPROC
DEF PROCcleanup
PROC_killtimer(tID1%)
PROC_killtimer(tID2%)
PROC_killtimer(tID3%)
ENDPROC
C
#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)
OpenMP
Compile with gcc -std=c99 -fopenmp
:
#include <stdio.h>
#include <omp.h>
int main()
{
const char *str[] = { "Enjoy", "Rosetta", "Code" };
#pragma omp parallel for num_threads(3)
for (int i = 0; i < 3; i++)
printf("%s\n", str[i]);
return 0;
}
C#
With Threads
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
With Tasks
using System;
using System.Threading.Tasks;
public class Program
{
static async Task Main() {
Task t1 = Task.Run(() => Console.WriteLine("Enjoy"));
Task t2 = Task.Run(() => Console.WriteLine("Rosetta"));
Task t3 = Task.Run(() => Console.WriteLine("Code"));
await Task.WhenAll(t1, t2, t3);
}
}
With a parallel loop
using System;
using System.Threading.Tasks;
public class Program
{
static void Main() => Parallel.ForEach(new[] {"Enjoy", "Rosetta", "Code"}, s => Console.WriteLine(s));
}
C++
The following example compiles with GCC 4.7.
g++ -std=c++11 -D_GLIBCXX_USE_NANOSLEEP -o concomp concomp.cpp
#include <thread>
#include <iostream>
#include <vector>
#include <random>
#include <chrono>
int main()
{
std::random_device rd;
std::mt19937 eng(rd()); // mt19937 generator with a hardware random seed.
std::uniform_int_distribution<> dist(1,1000);
std::vector<std::thread> threads;
for(const auto& str: {"Enjoy\n", "Rosetta\n", "Code\n"}) {
// between 1 and 1000ms per our distribution
std::chrono::milliseconds duration(dist(eng));
threads.emplace_back([str, duration](){
std::this_thread::sleep_for(duration);
std::cout << str;
});
}
for(auto& t: threads) t.join();
return 0;
}
Output:
Enjoy Code Rosetta
#include <iostream>
#include <ppl.h> // MSVC++
void a(void) { std::cout << "Eat\n"; }
void b(void) { std::cout << "At\n"; }
void c(void) { std::cout << "Joe's\n"; }
int main()
{
// function pointers
Concurrency::parallel_invoke(&a, &b, &c);
// C++11 lambda functions
Concurrency::parallel_invoke(
[]{ std::cout << "Enjoy\n"; },
[]{ std::cout << "Rosetta\n"; },
[]{ std::cout << "Code\n"; }
);
return 0;
}
Output:
Joe's Eat At Enjoy Code Rosetta
Cind
execute() {
{# host.println("Enjoy");
# host.println("Rosetta");
# host.println("Code"); }
}
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)))
Using the new (2013) core.async library, "go blocks" can execute asynchronously, sharing threads from a pool. This works even in ClojureScript (the JavaScript target of Clojure) on a single thread. The timeout call is there just to shuffle things up: note this delay doesn't block a thread.
(require '[clojure.core.async :refer [go <! timeout]])
(doseq [text ["Enjoy" "Rosetta" "Code"]]
(go
(<! (timeout (rand-int 1000))) ; wait a random fraction of a second,
(println text)))
CoffeeScript
Using Bash (or an equivalent shell)
JavaScript, which CoffeeScript compiles to, is single-threaded. This approach launches multiple process to achieve concurrency on Node.js:
{ exec } = require 'child_process'
for word in [ 'Enjoy', 'Rosetta', 'Code' ]
exec "echo #{word}", (err, stdout) ->
console.log stdout
Using Node.js
As stated above, CoffeeScript is single-threaded. This approach launches multiple Node.js processes to achieve concurrency.
# The "master" file.
{ fork } = require 'child_process'
path = require 'path'
child_name = path.join __dirname, 'child.coffee'
words = [ 'Enjoy', 'Rosetta', 'Code' ]
fork child_name, [ word ] for word in words
# child.coffee
console.log process.argv[ 2 ]
Common Lisp
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")))))
Crystal
Crystal requires the use of channels to ensure that the main fiber doesn't exit before any of the new fibers are done, since each fiber sleeping could return control to the main fiber.
require "channel"
require "fiber"
require "random"
done = Channel(Nil).new
"Enjoy Rosetta Code".split.map do |x|
spawn do
sleep Random.new.rand(0..500).milliseconds
puts x
done.send nil
end
end
3.times do
done.receive
end
D
import std.stdio, std.random, std.parallelism, core.thread, core.time;
void main() {
foreach (s; ["Enjoy", "Rosetta", "Code"].parallel(1)) {
Thread.sleep(uniform(0, 1000).dur!"msecs");
s.writeln;
}
}
Alternative version
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;
}
Dart
Future
Using Futures, called Promises in Javascript
import 'dart:math' show Random;
main(){
enjoy() .then( (e) => print(e) );
rosetta() .then( (r) => print(r) );
code() .then( (c) => print(c) );
}
// Create random number generator
var rng = Random();
// Each function returns a future that starts after a delay
// Like using setTimeout with a Promise in Javascript
enjoy() => Future.delayed( Duration( milliseconds: rng.nextInt( 10 ) ), () => "Enjoy");
rosetta() => Future.delayed( Duration( milliseconds: rng.nextInt( 10 ) ), () => "Rosetta");
code() => Future.delayed( Duration( milliseconds: rng.nextInt( 10 ) ), () => "Code");
Isolate
Using Isolates, similar to threads but each has its own memory, so they are more like Rust threads than C++
import 'dart:isolate' show Isolate, ReceivePort;
import 'dart:io' show exit, sleep;
import 'dart:math' show Random;
main() {
// Create ReceivePort to receive done messages
// Called a channel in other languages
var receiver = ReceivePort();
// Create job counter
var job_count = 3;
// Create job pool
var jobs = [ enjoy, rosetta, code ];
// Create random number generator
var rng = Random();
for ( var job in jobs ) {
// Sleep for random duration up to half a second
var sleep_time = Duration( milliseconds: rng.nextInt( 500 ) );
// Spawn Isolate to do work
// When finished the second argument will be sent to the receiver via the SendPort specified in onExit
Isolate.spawn( job, sleep_time, onExit: receiver.sendPort );
}
// Do something in main isolate
print("from main isolate\n");
// Register a listener on the ReceivePort, it gets called whenver something is sent on its SendPort
// We'll ignore the message with _ because we don't care about the data, just the event
receiver.listen( (_) {
// Decrement job counter
job_count -= 1;
// If jobs are all finished
if ( job_count == 0 ) {
print("\nall jobs finished!");
exit(0);
}
});
}
enjoy ( duration ) {
sleep( duration ) ;
print("Enjoy");
}
rosetta ( duration ) {
sleep( duration );
print("Rosetta");
}
code ( duration ) {
sleep( duration );
print("Code");
}
Delphi
program ConcurrentComputing;
{$APPTYPE CONSOLE}
uses SysUtils, Classes, Windows;
type
TRandomThread = class(TThread)
private
FString: string;
protected
procedure Execute; override;
public
constructor Create(const aString: string); overload;
end;
constructor TRandomThread.Create(const aString: string);
begin
inherited Create(False);
FreeOnTerminate := True;
FString := aString;
end;
procedure TRandomThread.Execute;
begin
Sleep(Random(5) * 100);
Writeln(FString);
end;
var
lThreadArray: Array[0..2] of THandle;
begin
Randomize;
lThreadArray[0] := TRandomThread.Create('Enjoy').Handle;
lThreadArray[1] := TRandomThread.Create('Rosetta').Handle;
lThreadArray[2] := TRandomThread.Create('Stone').Handle;
WaitForMultipleObjects(Length(lThreadArray), @lThreadArray, True, INFINITE);
end.
dodo0
fun parprint -> text, return
(
fork() -> return, throw
println(text, return)
| x
return()
)
| parprint
parprint("Enjoy") ->
parprint("Rosetta") ->
parprint("Code") ->
exit()
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)
}
EchoLisp
(lib 'tasks) ;; use the tasks library
(define (tprint line ) ;; task definition
(writeln _TASK line)
#f )
(for-each task-run ;; run three // tasks
(map (curry make-task tprint) '(Enjoy Rosetta code )))
→
#task:id:66:running Rosetta
#task:id:67:running code
#task:id:65:running Enjoy
Egel
import "prelude.eg"
import "io.ego"
using System
using IO
def main =
let _ = par (par [_ -> print "enjoy\n"]
[_ -> print "rosetta\n"])
[_ -> print "code\n"] in nop
Elixir
defmodule Concurrent do
def computing(xs) do
Enum.each(xs, fn x ->
spawn(fn ->
Process.sleep(:rand.uniform(1000))
IO.puts x
end)
end)
Process.sleep(1000)
end
end
Concurrent.computing ["Enjoy", "Rosetta", "Code"]
- Output:
Rosetta Code Enjoy
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
Euphoria
procedure echo(sequence s)
puts(1,s)
puts(1,'\n')
end procedure
atom task1,task2,task3
task1 = task_create(routine_id("echo"),{"Enjoy"})
task_schedule(task1,1)
task2 = task_create(routine_id("echo"),{"Rosetta"})
task_schedule(task2,1)
task3 = task_create(routine_id("echo"),{"Code"})
task_schedule(task3,1)
task_yield()
Output:
Code Rosetta Enjoy
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.
Factor
USE: concurrency.combinators
{ "Enjoy" "Rosetta" "Code" } [ print ] parallel-each
Forth
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
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
FreeBASIC
' FB 1.05.0 Win64
' Compiled with -mt switch (to use threadsafe runtiume)
' The 'ThreadCall' functionality in FB is based internally on LibFFi (see [https://github.com/libffi/libffi/blob/master/LICENSE] for license)
Sub thread1()
Print "Enjoy"
End Sub
Sub thread2()
Print "Rosetta"
End Sub
Sub thread3()
Print "Code"
End Sub
Print "Press any key to print next batch of 3 strings or ESC to quit"
Print
Do
Dim t1 As Any Ptr = ThreadCall thread1
Dim t2 As Any Ptr = ThreadCall thread2
Dim t3 As Any Ptr = ThreadCall thread3
ThreadWait t1
ThreadWait t2
ThreadWait t3
Print
Sleep
Loop While Inkey <> Chr(27)
Sample output
- Output:
Press any key to print next batch of 3 strings or ESC to quit Enjoy Code Rosetta Enjoy Rosetta Code
FutureBasic
include "NSLog.incl"
long priority(2)
priority(0) = _dispatchPriorityDefault
priority(1) = _dispatchPriorityHigh
priority(2) = _dispatchPriorityLow
dispatchglobal , priority(rnd(3)-1)
NSLog(@"Enjoy")
dispatchend
dispatchglobal , priority(rnd(3)-1)
NSLog(@"Rosetta")
dispatchend
dispatchglobal , priority(rnd(3)-1)
NSLog(@"Code")
dispatchend
HandleEvents
Go
Channel
Simple and direct solution: Start three goroutines, give each one a word. Each sleeps, then returns the word on a channel. The main goroutine prints words as they return. The print loop represents a checkpoint -- main doesn't exit until all words have been returned and printed.
This solution also shows a good practice for generating random numbers in concurrent goroutines. While certainly not needed for this RC task, in the more general case where you have a number of goroutines concurrently needing random numbers, the goroutines can suffer congestion if they compete heavily for the sole default library source. This can be relieved by having each goroutine create its own non-sharable source. Also particularly in cases where there might be a large number of concurrent goroutines, the source provided in subrepository rand package (exp/rand) can be a better choice than the standard library generator. The subrepo generator requires much less memory for "state" and is much faster to seed.
package main
import (
"fmt"
"golang.org/x/exp/rand"
"time"
)
func main() {
words := []string{"Enjoy", "Rosetta", "Code"}
seed := uint64(time.Now().UnixNano())
q := make(chan string)
for i, w := range words {
go func(w string, seed uint64) {
r := rand.New(rand.NewSource(seed))
time.Sleep(time.Duration(r.Int63n(1e9)))
q <- w
}(w, seed+uint64(i))
}
for i := 0; i < len(words); i++ {
fmt.Println(<-q)
}
}
Afterfunc
time.Afterfunc combines the sleep and the goroutine start. log.Println serializes output in the case goroutines attempt to print concurrently. sync.WaitGroup is used directly as a checkpoint.
package main
import (
"log"
"math/rand"
"os"
"sync"
"time"
)
func main() {
words := []string{"Enjoy", "Rosetta", "Code"}
rand.Seed(time.Now().UnixNano())
l := log.New(os.Stdout, "", 0)
var q sync.WaitGroup
q.Add(len(words))
for _, w := range words {
w := w
time.AfterFunc(time.Duration(rand.Int63n(1e9)), func() {
l.Println(w)
q.Done()
})
}
q.Wait()
}
Select
This solution might stretch the intent of the task a bit. It is concurrent but not parallel. Also it doesn't sleep and doesn't call the random number generator explicity. It works because the select statement is specified to make a "pseudo-random fair choice" among multiple channel operations.
package main
import "fmt"
func main() {
w1 := make(chan bool, 1)
w2 := make(chan bool, 1)
w3 := make(chan bool, 1)
for i := 0; i < 3; i++ {
w1 <- true
w2 <- true
w3 <- true
fmt.Println()
for i := 0; i < 3; i++ {
select {
case <-w1:
fmt.Println("Enjoy")
case <-w2:
fmt.Println("Rosetta")
case <-w3:
fmt.Println("Code")
}
}
}
}
Output:
Code Rosetta Enjoy Enjoy Rosetta Code Rosetta Enjoy Code
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.Concurrent
main = mapM_ forkIO [process1, process2, process3] where
process1 = putStrLn "Enjoy"
process2 = putStrLn "Rosetta"
process3 = putStrLn "Code"
A more elaborated example using MVars and a random running time per thread.
import Control.Concurrent
import System.Random
concurrent :: IO ()
concurrent = do
var <- newMVar [] -- use an MVar to collect the results of each thread
mapM_ (forkIO . task var) ["Enjoy", "Rosetta", "Code"] -- run 3 threads
putStrLn "Press Return to show the results." -- while we wait for the user,
-- the threads run
_ <- getLine
takeMVar var >>= mapM_ putStrLn -- read the results and show them on screen
where
-- "task" is a thread
task v s = do
randomRIO (1,10) >>= \r -> threadDelay (r * 100000) -- wait a while
val <- takeMVar v -- read the MVar and block other threads from reading it
-- until we write another value to it
putMVar v (s : val) -- append a text string to the MVar and block other
-- threads from writing to it unless it is read first
Icon and Unicon
The following code uses features exclusive to Unicon
procedure main()
L:=[ thread write("Enjoy"), thread write("Rosetta"), thread write("Code") ]
every wait(!L)
end
J
Using J's new threading primitives (in place of some sort of thread emulation):
reqthreads=: {{ 0&T.@''^:(0>.y-1 T.'')0 }}
dispatchwith=: (t.'')every
newmutex=: 10&T.
lock=: 11&T.
unlock=: 13&T.
synced=: {{
lock n
r=. u y
unlock n
r
}}
register=: {{ out=: out, y }} synced (newmutex 0)
task=: {{
reqthreads 3 NB. at least 3 worker threads
out=: EMPTY
#@> register dispatchwith ;:'Enjoy Rosetta Code'
out
}}
Sample use:
task''
Enjoy
Rosetta
Code
task''
Enjoy
Code
Rosetta
Java
Create a new Thread
array, shuffle the array, start each thread.
Thread[] threads = new Thread[3];
threads[0] = new Thread(() -> System.out.println("enjoy"));
threads[1] = new Thread(() -> System.out.println("rosetta"));
threads[2] = new Thread(() -> System.out.println("code"));
Collections.shuffle(Arrays.asList(threads));
for (Thread thread : threads)
thread.start();
An alternate demonstration
Uses CyclicBarrier to force all threads to wait until they're at the same point before executing the println, increasing the odds they'll print in a different order (otherwise, while the they may be executing in parallel, the threads are started sequentially and with such a short run-time, will usually output sequentially as well).
import java.util.concurrent.CyclicBarrier;
public class Threads
{
public static class DelayedMessagePrinter implements Runnable
{
private CyclicBarrier barrier;
private String msg;
public DelayedMessagePrinter(CyclicBarrier barrier, String msg)
{
this.barrier = barrier;
this.msg = msg;
}
public void run()
{
try
{ barrier.await(); }
catch (Exception e)
{ }
System.out.println(msg);
}
}
public static void main(String[] args)
{
CyclicBarrier barrier = new CyclicBarrier(3);
new Thread(new DelayedMessagePrinter(barrier, "Enjoy")).start();
new Thread(new DelayedMessagePrinter(barrier, "Rosetta")).start();
new Thread(new DelayedMessagePrinter(barrier, "Code")).start();
}
}
JavaScript
JavaScript now enjoys access to a concurrency library thanks to Web Workers. The Web Workers specification defines an API for spawning background scripts. This first code is the background script and should be in the concurrent_worker.js file.
self.addEventListener('message', function (event) {
self.postMessage(event.data);
self.close();
}, false);
This second block creates the workers, sends them a message and creates an event listener to handle the response.
var words = ["Enjoy", "Rosetta", "Code"];
var workers = [];
for (var i = 0; i < words.length; i++) {
workers[i] = new Worker("concurrent_worker.js");
workers[i].addEventListener('message', function (event) {
console.log(event.data);
}, false);
workers[i].postMessage(words[i]);
}
Julia
words = ["Enjoy", "Rosetta", "Code"]
function sleepprint(s)
sleep(rand())
println(s)
end
@sync for word in words
@async sleepprint(word)
end
Kotlin
// version 1.1.2
import java.util.concurrent.CyclicBarrier
class DelayedMessagePrinter(val barrier: CyclicBarrier, val msg: String) : Runnable {
override fun run() {
barrier.await()
println(msg)
}
}
fun main(args: Array<String>) {
val msgs = listOf("Enjoy", "Rosetta", "Code")
val barrier = CyclicBarrier(msgs.size)
for (msg in msgs) Thread(DelayedMessagePrinter(barrier, msg)).start()
}
- Output:
Sample output:
Code Rosetta Enjoy
LFE
;;;
;;; This is a straight port of the Erlang version.
;;;
;;; You can run this under the LFE REPL as follows:
;;;
;;; (slurp "concurrent-computing.lfe")
;;; (start)
;;;
(defmodule concurrent-computing
(export (start 0)))
(defun start ()
(lc ((<- word '("Enjoy" "Rosetta" "Code")))
(spawn (lambda () (say (self) word))))
(wait 2)
'ok)
(defun say (pid word)
(lfe_io:format "~p~n" (list word))
(! pid 'done))
(defun wait (n)
(receive
('done (case n
(0 0)
(_n (wait (- n 1)))))))
Logtalk
Works when using SWI-Prolog, XSB, or YAP as the backend compiler.
:- object(concurrency).
:- initialization(output).
output :-
threaded((
write('Enjoy'),
write('Rosetta'),
write('Code')
)).
:- end_object.
Lua
co = {}
co[1] = coroutine.create( function() print "Enjoy" end )
co[2] = coroutine.create( function() print "Rosetta" end )
co[3] = coroutine.create( function() print "Code" end )
math.randomseed( os.time() )
h = {}
i = 0
repeat
j = math.random(3)
if h[j] == nil then
coroutine.resume( co[j] )
h[j] = true
i = i + 1
end
until i == 3
M2000 Interpreter
Each thread executed in same scope where created. We can use static variables, which are at thread level, so in this example we have three A$,one for each thread. Each thread can use Thread This to send command, or using a known handler (number which return to k) to execute commands to other threads. Commands are HOLD,RESTART, ERASE, INTERVAL, EXECUTE.
Each thread has own stack of values, which deleted when erased. We can Push values to top of stack, or use Data to push to end of stack. A Read statement read from top of stack. In the example we Flush module's stack (modules use parent stack, functions get own stack), we place with Data strings and we read it using Read M$. We place the M$ to Static A$ (this can be done one time, because if A$ as static exist then interpreter skip expression without execute it).
All threads of a module erased when a module exit. Any block of code inside { } in Thread run without concurrency, when we use Thread.Plan Concurrent (when a thread runs we can't change Plan). Other plan is the sequential. Interval can be set to milliseconds.
Threads actually runs in Wait loop. We can use Main.Task as a loop which is thread also. Threads can be run when we wait for input in m2000 console, or for events from M2000 GUI forms, also. Events always run in sequential form.
Thread.Plan Concurrent
Module CheckIt {
Flush \\ empty stack of values
Data "Enjoy", "Rosetta", "Code"
For i=1 to 3 {
Thread {
Print A$
Thread This Erase
} As K
Read M$
Thread K Execute Static A$=M$
Thread K Interval Random(500,1000)
Threads
}
Rem : Wait 3000 ' we can use just a wait loop, or the main.task loop
\\ main.task exit if all threads erased
Main.Task 30 {
}
\\ when module exit all threads from this module get a signal to stop.
\\ we can use Threads Erase to erase all threads.
\\ Also if we press Esc we do the same
}
CheckIt
\\ we can define again the module, and now we get three time each name, but not every time three same names.
\\ if we change to Threads.Plan Sequential we get always the three same names
\\ Also in concurrent plan we can use a block to ensure that statements run without other thread executed in parallel.
Module CheckIt {
Flush \\ empty stack of values
Data "Enjoy", "Rosetta", "Code"
For i=1 to 3 {
Thread {
Print A$
Print A$
Print A$
Thread This Erase
} As K
Read M$
Thread K Execute Static A$=M$
Thread K Interval Random(500,530)
Threads
}
Rem : Wait 3000 ' we can use just a wait loop, or the main.task loop
\\ main.task exit if all threads erased
Main.Task 30 {
}
\\ when module exit all threads from this module get a signal to stop.
\\ we can use Threads Erase to erase all threads.
\\ Also if we press Esc we do the same
}
CheckIt
Mathematica / Wolfram Language
Parallelization requires Mathematica 7 or later
ParallelDo[
Pause[RandomReal[]];
Print[s],
{s, {"Enjoy", "Rosetta", "Code"}}
]
Mercury
:- module concurrent_computing.
:- interface.
:- import_module io.
:- pred main(io::di, io::uo) is cc_multi.
:- implementation.
:- import_module thread.
main(!IO) :-
spawn(io.print_cc("Enjoy\n"), !IO),
spawn(io.print_cc("Rosetta\n"), !IO),
spawn(io.print_cc("Code\n"), !IO).
Neko
/**
Concurrent computing, in Neko
*/
var thread_create = $loader.loadprim("std@thread_create", 2);
var subtask = function(message) {
$print(message, "\n");
}
/* The thread functions happen so fast as to look sequential */
thread_create(subtask, "Enjoy");
thread_create(subtask, "Rosetta");
thread_create(subtask, "Code");
/* slow things down */
var sys_sleep = $loader.loadprim("std@sys_sleep", 1);
var random_new = $loader.loadprim("std@random_new", 0);
var random_int = $loader.loadprim("std@random_int", 2);
var randomsleep = function(message) {
var r = random_new();
var sleep = random_int(r, 3);
sys_sleep(sleep);
$print(message, "\n");
}
$print("\nWith random delays\n");
thread_create(randomsleep, "Enjoy");
thread_create(randomsleep, "Rosetta");
thread_create(randomsleep, "Code");
/* Let the threads complete */
sys_sleep(4);
- Output:
prompt$ nekoc threading.neko prompt$ neko threading Enjoy Rosetta Code With random delays Rosetta Enjoy Code
Nim
Compile with nim --threads:on c concurrent
:
const str = ["Enjoy", "Rosetta", "Code"]
var thr: array[3, Thread[int32]]
proc f(i:int32) {.thread.} =
echo str[i]
for i in 0..thr.high:
createThread(thr[i], f, int32(i))
joinThreads(thr)
OpenMP
Compile with nim --passC:"-fopenmp" --passL:"-fopenmp" c concurrent
:
const str = ["Enjoy", "Rosetta", "Code"]
for i in 0||2:
echo str[i]
Thread Pools
Compile with nim --threads:on c concurrent
:
import threadpool
const str = ["Enjoy", "Rosetta", "Code"]
proc f(i: int) {.thread.} =
echo str[i]
for i in 0..str.high:
spawn f(i)
sync()
Objeck
bundle Default {
class MyThread from Thread {
New(name : String) {
Parent(name);
}
method : public : Run(param : Base) ~ Nil {
string := param->As(String);
string->PrintLine();
}
}
class Concurrent {
New() {
}
function : Main(args : System.String[]) ~ Nil {
t0 := MyThread->New("t0");
t1 := MyThread->New("t1");
t2 := MyThread->New("t2");
t0->Execute("Enjoy"->As(Base));
t1->Execute("Rosetta"->As(Base));
t2->Execute("Code"->As(Base));
}
}
}
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 () =
Random.self_init ();
List.iter (Thread.join) threads
Oforth
Oforth uses tasks to implement concurrent computing. A task is scheduled using #& on a function, method, block, ...
#[ "Enjoy" println ] &
#[ "Rosetta" println ] &
#[ "Code" println ] &
mapParallel method can be used to map a runnable on each element of a collection and returns a collection of results. Here, we println the string and return string size.
[ "Enjoy", "Rosetta", "Code" ] mapParallel(#[ dup . size ])
Ol
(import (otus random!))
(for-each (lambda (str)
(define timeout (rand! 999))
(async (lambda ()
(sleep timeout)
(print str))))
'("Enjoy" "Rosetta" "Code"))
- Output:
Code Enjoy Rosetta
ooRexx
-- this will launch 3 threads, with each thread given a message to print out.
-- I've added a stoplight to make each thread wait until given a go signal,
-- plus some sleeps to give the threads a chance to randomize the execution
-- order a little.
launcher = .launcher~new
launcher~launch
::class launcher
-- the launcher method. Guarded is the default, but let's make this
-- explicit here
::method launch guarded
runner1 = .runner~new(self, "Enjoy")
runner2 = .runner~new(self, "Rosetta")
runner3 = .runner~new(self, "Code")
-- let's give the threads a chance to settle in to the
-- starting line
call syssleep 1
guard off -- release the launcher lock. This is the starter's gun
-- this is a guarded method that the runners will call. They
-- will block until the launch method releases the object guard
::method block guarded
::class runner
::method init
use arg launcher, text
reply -- this creates the new thread
call syssleep .5 -- try to mix things up by sleeping
launcher~block -- wait for the go signal
call syssleep .5 -- add another sleep here
say text
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
PARI/GP
Here is a GP implementation using the bill-mt branch:
inline(func);
func(n)=print(["Enjoy","Rosetta","Code"][n]);
parapply(func,[1..3]);
This is a PARI implementation which uses fork()
internally. Note that the C solutions can be used instead if desired; this program demonstrates the native PARI capabilities instead.
For serious concurrency, see Appendix B of the User's Guide to the PARI Library which discusses a solution using tls on pthreads. (There are nontrivial issues with using PARI in this environment, do not attempt to blindly implement a C solution.)
void
foo()
{
if (pari_daemon()) {
// Original
if (pari_daemon()) {
// Original
pari_printf("Enjoy\n");
} else {
// Daemon #2
pari_printf("Code\n");
}
} else {
// Daemon #1
pari_printf("Rosetta\n");
}
}
See also Bill Allombert's slides on parallel programming in GP.
Pascal
modified for linux. Using simple running thread-counter to circumvent WaitForMultipleObjects.
Output of difference of sleep time and true sleep time ( running with 0..1999 threads you see once a while 1)
program ConcurrentComputing;
{$IFdef FPC}
{$MODE DELPHI}
{$ELSE}
{$APPTYPE CONSOLE}
{$ENDIF}
uses
{$IFDEF UNIX}
cthreads,
{$ENDIF}
SysUtils, Classes;
type
TRandomThread = class(TThread)
private
FString: string;
T0 : Uint64;
protected
procedure Execute; override;
public
constructor Create(const aString: string); overload;
end;
const
MyStrings: array[0..2] of String = ('Enjoy ','Rosetta ','Code ');
var
gblRunThdCnt : LongWord = 0;
constructor TRandomThread.Create(const aString: string);
begin
inherited Create(False);
FreeOnTerminate := True;
FString := aString;
interlockedincrement(gblRunThdCnt);
end;
procedure TRandomThread.Execute;
var
i : NativeInt;
begin
i := Random(300);
T0 := GettickCount64;
Sleep(i);
//output of difference in time
Writeln(FString,i:4,GettickCount64-T0 -i:2);
interlockeddecrement(gblRunThdCnt);
end;
var
lThreadArray: Array[0..9] of THandle;
i : NativeInt;
begin
Randomize;
gblRunThdCnt := 0;
For i := low(lThreadArray) to High(lThreadArray) do
lThreadArray[i] := TRandomThread.Create(Format('%9s %4d',[myStrings[Random(3)],i])).Handle;
while gblRunThdCnt > 0 do
sleep(125);
end.
- Output:
Enjoy 4 16 0 Code 0 22 0 Code 1 32 0 Rosetta 7 117 0 Enjoy 2 137 0 Code 6 214 0 Code 5 252 0 Enjoy 3 299 0
Perl
use threads;
use Time::HiRes qw(sleep);
$_->join for map {
threads->create(sub {
sleep rand;
print shift, "\n";
}, $_)
} qw(Enjoy Rosetta Code);
Or using coroutines provided by
use feature qw( say );
use Coro;
use Coro::Timer qw( sleep );
$_->join for map {
async {
sleep rand;
say @_;
} $_
} qw( Enjoy Rosetta Code );
Phix
Without the sleep it is almost always Enjoy Rosetta Code, because create_thread() is more costly than echo(), as the former has to create a new call stack etc.
The lock prevents the displays from mangling each other.
without js -- (threads) procedure echo(string s) sleep(rand(100)/100) enter_cs() puts(1,s) puts(1,'\n') leave_cs() end procedure constant threads = {create_thread(routine_id("echo"),{"Enjoy"}), create_thread(routine_id("echo"),{"Rosetta"}), create_thread(routine_id("echo"),{"Code"})} wait_thread(threads) puts(1,"done") {} = wait_key()
PicoLisp
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
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
Pike
Using POSIX threads:
int main() {
// Start threads and wait for them to finish
({
Thread.Thread(write, "Enjoy\n"),
Thread.Thread(write, "Rosetta\n"),
Thread.Thread(write, "Code\n")
})->wait();
// Exit program
exit(0);
}
Output:
Enjoy Rosetta Code
Using Pike's backend:
int main(int argc, array argv)
{
call_out(write, random(1.0), "Enjoy\n");
call_out(write, random(1.0), "Rosetta\n");
call_out(write, random(1.0), "Code\n");
call_out(exit, 1, 0);
return -1; // return -1 starts the backend which makes Pike run until exit() is called.
}
Output:
Rosetta Code Enjoy
PowerShell
Using Background Jobs:
$Strings = "Enjoy","Rosetta","Code"
$SB = {param($String)Write-Output $String}
foreach($String in $Strings) {
Start-Job -ScriptBlock $SB -ArgumentList $String | Out-Null
}
Get-Job | Wait-Job | Receive-Job
Get-Job | Remove-Job
Using .NET Runspaces:
$Strings = "Enjoy","Rosetta","Code"
$SB = {param($String)Write-Output $String}
$Pool = [RunspaceFactory]::CreateRunspacePool(1, 3)
$Pool.ApartmentState = "STA"
$Pool.Open()
foreach ($String in $Strings) {
$Pipeline = [System.Management.Automation.PowerShell]::create()
$Pipeline.RunspacePool = $Pool
[void]$Pipeline.AddScript($SB).AddArgument($String)
$AsyncHandle = $Pipeline.BeginInvoke()
$Pipeline.EndInvoke($AsyncHandle)
$Pipeline.Dispose()
}
$Pool.Close()
Prolog
This example works in SWI-Prolog. It may work in other Prolog implementations too.
Create a separate thread for each word. Join the threads to make sure they complete before the program exits.
main :-
thread_create(say("Enjoy"),A,[]),
thread_create(say("Rosetta"),B,[]),
thread_create(say("Code"),C,[]),
thread_join(A,_),
thread_join(B,_),
thread_join(C,_).
say(Message) :-
Delay is random_float,
sleep(Delay),
writeln(Message).
PureBasic
Global mutex = CreateMutex()
Procedure Printer(*str)
LockMutex(mutex)
PrintN( PeekS(*str) )
UnlockMutex(mutex)
EndProcedure
If OpenConsole()
LockMutex(mutex)
thread1 = CreateThread(@Printer(), @"Enjoy")
thread2 = CreateThread(@Printer(), @"Rosetta")
thread3 = CreateThread(@Printer(), @"Code")
UnlockMutex(mutex)
WaitThread(thread1)
WaitThread(thread2)
WaitThread(thread3)
Print(#CRLF$ + #CRLF$ + "Press ENTER to exit")
Input()
CloseConsole()
EndIf
FreeMutex(mutex)
Python
Using asyncio module (I know almost nothing about it, so feel free to improve it :-)):
import asyncio
async def print_(string: str) -> None:
print(string)
async def main():
strings = ['Enjoy', 'Rosetta', 'Code']
coroutines = map(print_, strings)
await asyncio.gather(*coroutines)
if __name__ == '__main__':
asyncio.run(main())
Using the new to Python 3.2 concurrent.futures library and choosing to use processes over threads; the example will use up to as many processes as your machine has cores. This doesn't however guarantee an order of sub-process results.
Python 3.2 (r32:88445, Feb 20 2011, 21:30:00) [MSC v.1500 64 bit (AMD64)] on win 32
Type "help", "copyright", "credits" or "license" for more information.
>>> from concurrent import futures
>>> with futures.ProcessPoolExecutor() as executor:
... _ = list(executor.map(print, 'Enjoy Rosetta Code'.split()))
...
Enjoy
Rosetta
Code
>>>
import threading
import random
def echo(text):
print(text)
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(text):
print(text)
for text in ["Enjoy", "Rosetta", "Code"]:
threading.Timer(random.random(), echo, (text,)).start()
threading.Thread
import random, sys, time
import threading
lock = threading.Lock()
def echo(s):
time.sleep(1e-2*random.random())
# use `.write()` with lock due to `print` prints empty lines occasionally
with lock:
sys.stdout.write(s)
sys.stdout.write('\n')
for line in 'Enjoy Rosetta Code'.split():
threading.Thread(target=echo, args=(line,)).start()
multiprocessing
from __future__ import print_function
from multiprocessing import Pool
def main():
p = Pool()
p.map(print, 'Enjoy Rosetta Code'.split())
if __name__=="__main__":
main()
twisted
import random
from twisted.internet import reactor, task, defer
from twisted.python.util import println
delay = lambda: 1e-4*random.random()
d = defer.DeferredList([task.deferLater(reactor, delay(), println, line)
for line in 'Enjoy Rosetta Code'.split()])
d.addBoth(lambda _: reactor.stop())
reactor.run()
gevent
from __future__ import print_function
import random
import gevent
delay = lambda: 1e-4*random.random()
gevent.joinall([gevent.spawn_later(delay(), print, line)
for line in 'Enjoy Rosetta Code'.split()])
Racket
Threads provide a simple API for concurrent programming.
#lang racket
(for ([str '("Enjoy" "Rosetta" "Code")])
(thread (λ () (displayln str))))
In addition to "thread" which is implemented as green threads (useful for IO etc), Racket has "futures" and "places" which are similar tools for using multiple OS cores.
Raku
(formerly Perl 6)
my @words = <Enjoy Rosetta Code>;
@words.race(:batch(1)).map: { sleep rand; say $_ };
- Output:
Code Rosetta Enjoy
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
Main(0,0)
|:
Print["Enjoy"]
Print["Rosetta"]
Print["Code"]
:|
In Rhope, expressions with no shared dependencies run in parallel by default.
Ruby
%w{Enjoy Rosetta Code}.map do |x|
Thread.new do
sleep rand
puts x
end
end.each do |t|
t.join
end
Rust
extern crate rand; // not needed for recent versions
use std::thread;
use rand::thread_rng;
use rand::distributions::{Range, IndependentSample};
fn main() {
let mut rng = thread_rng();
let rng_range = Range::new(0u32, 100);
for word in "Enjoy Rosetta Code".split_whitespace() {
let snooze_time = rng_range.ind_sample(&mut rng);
let local_word = word.to_owned();
std::thread::spawn(move || {
thread::sleep_ms(snooze_time);
println!("{}", local_word);
});
}
thread::sleep_ms(1000);
}
Scala
import scala.actors.Futures
List("Enjoy", "Rosetta", "Code").map { x =>
Futures.future {
Thread.sleep((Math.random * 1000).toInt)
println(x)
}
}.foreach(_())
Scheme
(parallel-execute (lambda () (print "Enjoy"))
(lambda () (print "Rosetta"))
(lambda () (print "Code")))
If your implementation doesn't provide parallel-execute, it can be implemented with SRFI-18.
(import (srfi 18))
(define (parallel-execute . thunks)
(let ((threads (map make-thread thunks)))
(for-each thread-start! threads)
(for-each thread-join! threads)))
Sidef
A very basic threading support is provided by the Block.fork() method:
var a = <Enjoy Rosetta Code>
a.map{|str|
{ Sys.sleep(1.rand)
say str
}.fork
}.map{|thr| thr.wait }
- Output:
Enjoy Code Rosetta
Slope
(coeval
(display "Enjoy")
(display "Rosetta")
(display "Code"))
Swift
Using Grand Central Dispatch with concurrent queues.
import Foundation
let myList = ["Enjoy", "Rosetta", "Code"]
for word in myList {
dispatch_async(dispatch_get_global_queue(0, 0)) {
NSLog(word)
}
}
dispatch_main()
- Output:
2015-02-05 10:15:01.831 rosettaconcurrency[1917:37905] Code 2015-02-05 10:15:01.831 rosettaconcurrency[1917:37902] Enjoy 2015-02-05 10:15:01.831 rosettaconcurrency[1917:37904] Rosetta
Standard ML
Works with PolyML
structure TTd = Thread.Thread ;
structure TTm = Thread.Mutex ;
val threadedStringList = fn tasks:string list =>
let
val mx = TTm.mutex () ;
val taskstore = ref tasks ;
fun makeFastRand () = Real.rem (Time.toReal (Time.now ()),1.0)
val doTask = fn () =>
let
val mytask : string ref = ref "" ;
in
( TTm.lock mx ; mytask := hd ( !taskstore ) ; taskstore:= tl (!taskstore) ; TTm.unlock mx ;
Posix.Process.sleep (Time.fromReal (makeFastRand ())) ;
TTm.lock mx ; print ( !mytask ^ "\n") ; TTm.unlock mx ;
TTd.exit ()
)
end
in
List.tabulate ( length tasks , fn i => TTd.fork (doTask , []) )
end ;
call
threadedStringList [ "Enjoy","Rosetta","Code" ]; Rosetta Code Enjoy
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
UnixPipes
(echo "Enjoy" & echo "Rosetta"& echo "Code"&)
VBA
Three tasks scheduled for the same time with OnTime. The last scheduled task gets executed first.
Private Sub Enjoy()
Debug.Print "Enjoy"
End Sub
Private Sub Rosetta()
Debug.Print "Rosetta"
End Sub
Private Sub Code()
Debug.Print "Code"
End Sub
Public Sub concurrent()
when = Now + TimeValue("00:00:01")
Application.OnTime when, "Enjoy"
Application.OnTime when, "Rosetta"
Application.OnTime when, "Code"
End Sub
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
Alternative version
Imports System.Threading
Module Module1
Dim rnd As New Random()
Sub Main()
Parallel.ForEach("Enjoy Rosetta Code".Split(" "), Sub(s)
Thread.Sleep(rnd.Next(25)) : Console.WriteLine(s)
End Sub)
End Sub
End Module
- Output:
Rosetta Enjoy Code
V (Vlang)
Porting of Go code
import time
import rand
import rand.pcg32
import rand.seed
fn main() {
words := ['Enjoy', 'Rosetta', 'Code']
seed_u64 := u64(time.now().unix_time_milli())
q := chan string{}
for i, w in words {
go fn (q chan string, w string, seed_u64 u64) {
mut rng := pcg32.PCG32RNG{}
time_seed := seed.time_seed_array(2)
seed_arr := [u32(seed_u64), u32(seed_u64 >> 32), time_seed[0], time_seed[1]]
rng.seed(seed_arr)
time.sleep(time.Duration(rng.i64n(1_000_000_000)))
q <- w
}(q, w, seed_u64 + u64(i))
}
for _ in 0 .. words.len {
println(<-q)
}
}
Vlang Idiomatic version
import time
import rand
import rand.pcg32
import rand.seed
fn main() {
words := ['Enjoy', 'Rosetta', 'Code']
mut threads := []thread{} // mutable array to hold the id of the thread
for w in words {
threads << go fn (w string) { // record the thread
mut rng := pcg32.PCG32RNG{}
time_seed := seed.time_seed_array(4) // the time derived array to seed the random generator
rng.seed(time_seed)
time.sleep(time.Duration(rng.i64n(1_000_000_000)))
println(w)
}(w)
}
threads.wait() // join the thread waiting. wait() is defined for threads and arrays of threads
}
- Output:
CodeRosetta Enjoy
Rosetta Enjoy
Code
Wren
import "random" for Random
var words = ["Enjoy", "Rosetta", "Code"]
var rand = Random.new()
for (h in 1..3) {
var fibers = List.filled(3, null)
for (i in 0..2) fibers[i] = Fiber.new { System.print(words[i]) }
var called = List.filled(3, false)
var j = 0
while (j < 3) {
var k = rand.int(3)
if (!called[k]) {
fibers[k].call()
called[k] = true
j = j + 1
}
}
System.print()
}
- Output:
Sample run:
Enjoy Code Rosetta Code Enjoy Rosetta Rosetta Enjoy Code
XPL0
Works on Raspberry Pi using XPL0 version 3.2. Processes actually execute simultaneously, one per CPU core (beyond single-core RPi-1). Lock is necessary to enable one line to finish printing before another line starts.
int Key, Process;
[Key:= SharedMem(4); \allocate 4 bytes of memory common to all processes
Process:= Fork(2); \start 2 child processes
case Process of
0: [Lock(Key); Text(0, "Enjoy"); CrLf(0); Unlock(Key)]; \parent process
1: [Lock(Key); Text(0, "Rosetta"); CrLf(0); Unlock(Key)]; \child process
2: [Lock(Key); Text(0, "Code"); CrLf(0); Unlock(Key)] \child process
other [Lock(Key); Text(0, "Error"); CrLf(0); Unlock(Key)];
Join(Process); \wait for all child processes to finish
]
- Output:
Code Enjoy Rosetta
zkl
fcn{println("Enjoy")}.launch(); // thread
fcn{println("Rosetta")}.strand(); // co-op thread
fcn{println("Code")}.future(); // another thread type
- Output:
Rosetta Code Enjoy
- Programming Tasks
- Concurrency
- Basic language learning
- Ada
- ALGOL 68
- APL
- Astro
- BASIC
- BaCon
- Gomp
- BBC BASIC
- C
- Pthread
- C sharp
- C++
- Microsoft Parallel Patterns Library (PPL)
- Cind
- Clojure
- CoffeeScript
- Common Lisp
- Bordeaux Threads
- Crystal
- D
- Tango
- Dart
- Delphi
- Dodo0
- E
- EchoLisp
- Egel
- Elixir
- Erlang
- Euphoria
- F Sharp
- Factor
- Forth
- Fortran
- FreeBASIC
- FutureBasic
- Go
- Groovy
- Haskell
- Unicon
- J
- Java
- JavaScript
- Julia
- Kotlin
- LFE
- Logtalk
- Lua
- M2000 Interpreter
- Mathematica
- Wolfram Language
- Mercury
- Neko
- Nim
- Objeck
- OCaml
- Oforth
- Ol
- OoRexx
- Oz
- PARI/GP
- Pascal
- Perl
- Coro
- Phix
- PicoLisp
- Pike
- PowerShell
- Prolog
- PureBasic
- Python
- Racket
- Raku
- Raven
- Rhope
- Ruby
- Rust
- Rand
- Scala
- Scheme
- Sidef
- Slope
- Swift
- Standard ML
- Tcl
- UnixPipes
- VBA
- Visual Basic .NET
- V (Vlang)
- Wren
- XPL0
- Zkl
- AWK/Omit
- Bc/Omit
- Brlcad/Omit
- Dc/Omit
- GUISS/Omit
- Lilypond/Omit
- Maxima/Omit
- Metafont/Omit
- Openscad/Omit
- TI-83 BASIC/Omit
- TI-89 BASIC/Omit
- TPP/Omit
- Vim Script/Omit
- ZX Spectrum Basic/Omit
- Axe/Omit