Szymański's algorithm: Difference between revisions

m
→‎{{header|Wren}}: Changed to Wren S/H
m (→‎{{header|Julia}}: n not used)
m (→‎{{header|Wren}}: Changed to Wren S/H)
 
(10 intermediate revisions by 6 users not shown)
Line 1:
{{draft task}}
 
<em>Szymański's algorithm</em> is a is a mutual exclusion algorithm devised by computer scientist Bolesław Szymański.
 
The algorithm allows mutiple processes or tasks to access a serial resource without conflict, using only linear waiting times.
It has application in multitasking and communications, especially if there is a need for massive parallelism with limited
limited allowed waiting times for access to resources by the parallel program's components.
 
;Task
Line 15:
;* [[https://dl.acm.org/doi/10.1145/55364.55425 ACM digital entry for Szymański's paper]]
 
"""
=={{header|Julia}}==
<syntaxhighlight lang="julia">"""
Szymański's algorithm reference:
Boleslaw K. Szymanski. A simple solution to Lamport's concurrent programming problem with linear wait.
Line 24 ⟶ 23:
"""
 
=={{header|C#}}==
using ThreadSafeDicts # implement a single lock on all thread's shared values as a lockable Dict (keyed by thread id)
{{trans|Julia}}
<syntaxhighlight lang="C#">
using System;
using System.Collections.Concurrent;
using System.Linq;
using System.Threading;
 
class Program
{
private static ConcurrentDictionary<int, int> dict = new ConcurrentDictionary<int, int>();
private static int criticalValue = 1;
private static readonly object lockObject = new object();
 
static void Main(string[] args)
{
TestSzymanski(20);
}
 
static int Flag(int id)
{
return dict.GetOrAdd(id, 0);
}
 
static void RunSzymanski(int id, int[] allszy)
{
var others = allszy.Where(t => t != id).ToArray();
dict[id] = 1; // Standing outside waiting room
while (others.Any(t => Flag(t) >= 3))
{
Thread.Yield();
}
dict[id] = 3; // Standing in doorway
if (others.Any(t => Flag(t) == 1))
{
dict[id] = 2; // Waiting for other processes to enter
while (!others.Any(t => Flag(t) == 4))
{
Thread.Yield();
}
}
dict[id] = 4; // The door is closed
foreach (var t in others)
{
if (t >= id) continue;
while (Flag(t) > 1)
{
Thread.Yield();
}
}
 
// critical section
lock (lockObject)
{
criticalValue += id * 3;
criticalValue /= 2;
Console.WriteLine($"Thread {id} changed the critical value to {criticalValue}.");
}
// end critical section
 
// Exit protocol
foreach (var t in others)
{
if (t <= id) continue;
while (!new[] { 0, 1, 4 }.Contains(Flag(t)))
{
Thread.Yield();
}
}
dict[id] = 0; // Leave. Reopen door if nobody is still in the waiting room
}
 
static void TestSzymanski(int N)
{
int[] allszy = Enumerable.Range(1, N).ToArray();
var threads = allszy.Select(i => new Thread(() => RunSzymanski(i, allszy))).ToArray();
 
foreach (var thread in threads)
{
thread.Start();
}
 
foreach (var thread in threads)
{
thread.Join();
}
}
}
</syntaxhighlight>
{{out}}
<pre>
Thread 1 changed the critical value to 2.
Thread 2 changed the critical value to 4.
Thread 3 changed the critical value to 6.
Thread 4 changed the critical value to 9.
Thread 5 changed the critical value to 12.
Thread 6 changed the critical value to 15.
Thread 7 changed the critical value to 18.
Thread 8 changed the critical value to 21.
Thread 9 changed the critical value to 24.
Thread 10 changed the critical value to 27.
Thread 11 changed the critical value to 30.
Thread 12 changed the critical value to 33.
Thread 13 changed the critical value to 36.
Thread 14 changed the critical value to 39.
Thread 15 changed the critical value to 42.
Thread 16 changed the critical value to 45.
Thread 17 changed the critical value to 48.
Thread 18 changed the critical value to 51.
Thread 19 changed the critical value to 54.
Thread 20 changed the critical value to 57.
 
</pre>
 
 
=={{header|FreeBASIC}}==
<syntaxhighlight lang="vb">Const MAX_THREADS = 6
 
Dim Shared As Any Ptr ttylock
Dim Shared As Integer criticalValue = 1
 
Sub thread( Byval userdata As Any Ptr )
''
'' This MutexLock makes simultaneously running threads wait for each
'' other, so only one at a time can continue and print output.
'' Otherwise, their Locates would interfere, since there is only one
'' cursor.
''
'' It's impossible to predict the order in which threads will arrive
'' here and which one will be the first to acquire the lock thus
'' causing the rest to wait.
''
Mutexlock ttylock
Dim As Integer id = Cint(userdata)
criticalvalue += id * 3
criticalvalue \= 2
Sleep 25, 1
Print Using "Thread # changed the critical value to ##."; id; criticalvalue
'' MutexUnlock releases the lock and lets other threads acquire it.
Mutexunlock ttylock
End Sub
 
'' Create a mutex to syncronize the threads
ttylock = Mutexcreate()
 
'' Create child threads
Dim As Any Ptr handles(1 To MAX_THREADS)
For i As Integer = 1 To MAX_THREADS
handles(i) = Threadcreate(@thread, Cptr(Any Ptr, i))
If handles(i) = 0 Then
Print "Error creating thread:"; i
Exit For
End If
Next
 
'' This is the main thread. Now wait until all child threads have finished.
For i As Integer = 1 To MAX_THREADS
If handles(i) <> 0 Then
Threadwait(handles(i))
End If
Next
 
'' Clean up when finished
Mutexdestroy(ttylock)
 
Sleep</syntaxhighlight>
{{out}}
<pre>Thread 1 changed the critical value to 2.
Thread 4 changed the critical value to 7.
Thread 3 changed the critical value to 8.
Thread 2 changed the critical value to 7.
Thread 5 changed the critical value to 11.
Thread 6 changed the critical value to 14.</pre>
 
=={{header|Julia}}==
<syntaxhighlight lang="julia">using ThreadSafeDicts # implement a single lock on all thread's shared values as a lockable Dict (keyed by a process id)
 
const dict = ThreadSafeDict()
Line 32 ⟶ 208:
 
""" test the implementation on each thread, concurrently"""
function runSzymański(id, allszy)
id = Threads.threadid()
others = filter(!=(id), allszy)
dict[id] = 1 # Standing outside waiting room
Line 71 ⟶ 246:
end
 
function test_Szymański(N)
allszy = collect(1:Threads.nthreads()N)
@Threads.threads for _i in eachindex(allszy)
runSzymański(i, allszy)
end
end
 
test_Szymański(20)
</syntaxhighlight>{{out}}
<pre>
Thread 31 changed the critical value to 52.
Thread 52 changed the critical value to 104.
Thread 15 changed the critical value to 69.
Thread 29 changed the critical value to 618.
Thread 412 changed the critical value to 927.
Thread 615 changed the critical value to 1336.
Thread 18 changed the critical value to 45.
Thread 3 changed the critical value to 27.
Thread 6 changed the critical value to 22.
Thread 10 changed the critical value to 26.
Thread 13 changed the critical value to 32.
Thread 16 changed the critical value to 40.
Thread 19 changed the critical value to 48.
Thread 4 changed the critical value to 30.
Thread 7 changed the critical value to 25.
Thread 11 changed the critical value to 29.
Thread 14 changed the critical value to 35.
Thread 17 changed the critical value to 43.
Thread 20 changed the critical value to 51.
Thread 8 changed the critical value to 37.
</pre>
 
=={{header|Phix}}==
{{trans|Wren}}
Uses threads rather than tasks. While there ''is'' a task_yield(), there isn't a thread_yield() [maybe I should add one], so used sleep(0.01) instead.
<!--<syntaxhighlight lang="phix">(notonline)-->
<span style="color: #008080;">without</span> <span style="color: #008080;">js</span> <span style="color: #000080;font-style:italic;">-- (no support for threads in a browser, as yet...)</span>
<span style="color: #008080;">constant</span> <span style="color: #000000;">nthreads</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">6</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">flags</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">repeat</span><span style="color: #0000FF;">(</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">nthreads</span><span style="color: #0000FF;">)</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">criticalValue</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">1</span>
<span style="color: #008080;">enum</span> <span style="color: #000000;">lt3</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">ne1</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">ne4</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">in014</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">all_others</span><span style="color: #0000FF;">(</span><span style="color: #004080;">integer</span> <span style="color: #000000;">id</span><span style="color: #0000FF;">,</span><span style="color: #000000;">chk</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">nthreads</span> <span style="color: #008080;">do</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">!=</span><span style="color: #000000;">id</span> <span style="color: #008080;">then</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">fi</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">flags</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]</span>
<span style="color: #008080;">if</span> <span style="color: #0000FF;">(</span><span style="color: #000000;">chk</span><span style="color: #0000FF;">=</span><span style="color: #000000;">lt3</span> <span style="color: #008080;">and</span> <span style="color: #000000;">fi</span><span style="color: #0000FF;">>=</span><span style="color: #000000;">3</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">or</span> <span style="color: #0000FF;">(</span><span style="color: #000000;">chk</span><span style="color: #0000FF;">=</span><span style="color: #000000;">ne1</span> <span style="color: #008080;">and</span> <span style="color: #000000;">fi</span><span style="color: #0000FF;">==</span><span style="color: #000000;">1</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">or</span> <span style="color: #0000FF;">(</span><span style="color: #000000;">chk</span><span style="color: #0000FF;">=</span><span style="color: #000000;">ne4</span> <span style="color: #008080;">and</span> <span style="color: #000000;">fi</span><span style="color: #0000FF;">==</span><span style="color: #000000;">4</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">or</span> <span style="color: #0000FF;">(</span><span style="color: #000000;">chk</span><span style="color: #0000FF;">=</span><span style="color: #000000;">in014</span> <span style="color: #008080;">and</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">></span><span style="color: #000000;">id</span> <span style="color: #008080;">and</span> <span style="color: #008080;">not</span> <span style="color: #7060A8;">find</span><span style="color: #0000FF;">(</span><span style="color: #000000;">fi</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">4</span><span style="color: #0000FF;">}))</span> <span style="color: #008080;">then</span>
<span style="color: #008080;">return</span> <span style="color: #004600;">false</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #008080;">return</span> <span style="color: #004600;">true</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #008080;">procedure</span> <span style="color: #000000;">runSzymanski</span><span style="color: #0000FF;">(</span><span style="color: #004080;">integer</span> <span style="color: #000000;">id</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">flags</span><span style="color: #0000FF;">[</span><span style="color: #000000;">id</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">1</span> <span style="color: #000080;font-style:italic;">// Standing outside waiting room</span>
<span style="color: #008080;">while</span> <span style="color: #008080;">not</span> <span style="color: #000000;">all_others</span><span style="color: #0000FF;">(</span><span style="color: #000000;">id</span><span style="color: #0000FF;">,</span><span style="color: #000000;">lt3</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span> <span style="color: #000080;font-style:italic;">// Wait for open door </span>
<span style="color: #7060A8;">sleep</span><span style="color: #0000FF;">(</span><span style="color: #000000;">0.01</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">while</span>
<span style="color: #000000;">flags</span><span style="color: #0000FF;">[</span><span style="color: #000000;">id</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">3</span> <span style="color: #000080;font-style:italic;">// Standing in doorway</span>
<span style="color: #008080;">if</span> <span style="color: #008080;">not</span> <span style="color: #000000;">all_others</span><span style="color: #0000FF;">(</span><span style="color: #000000;">id</span><span style="color: #0000FF;">,</span><span style="color: #000000;">ne1</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">then</span> <span style="color: #000080;font-style:italic;">// Another thread is waiting to enter</span>
<span style="color: #000000;">flags</span><span style="color: #0000FF;">[</span><span style="color: #000000;">id</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">2</span> <span style="color: #000080;font-style:italic;">// Waiting for other threads to enter</span>
<span style="color: #008080;">while</span> <span style="color: #008080;">not</span> <span style="color: #000000;">all_others</span><span style="color: #0000FF;">(</span><span style="color: #000000;">id</span><span style="color: #0000FF;">,</span><span style="color: #000000;">ne4</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span> <span style="color: #000080;font-style:italic;">// Wait for a thread to enter & close door</span>
<span style="color: #7060A8;">sleep</span><span style="color: #0000FF;">(</span><span style="color: #000000;">0.01</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">while</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #000000;">flags</span><span style="color: #0000FF;">[</span><span style="color: #000000;">id</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">4</span> <span style="color: #000080;font-style:italic;">// The door is closed</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">t</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">id</span><span style="color: #0000FF;">-</span><span style="color: #000000;">1</span> <span style="color: #008080;">do</span> <span style="color: #000080;font-style:italic;">// Wait for everyone of lower id to exit</span>
<span style="color: #008080;">while</span> <span style="color: #000000;">flags</span><span style="color: #0000FF;">[</span><span style="color: #000000;">t</span><span style="color: #0000FF;">]></span><span style="color: #000000;">1</span> <span style="color: #008080;">do</span> <span style="color: #7060A8;">sleep</span><span style="color: #0000FF;">(</span><span style="color: #000000;">0.01</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">end</span> <span style="color: #008080;">while</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #000080;font-style:italic;">// critical section</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">pcv</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">criticalValue</span>
<span style="color: #000000;">criticalValue</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">floor</span><span style="color: #0000FF;">((</span><span style="color: #000000;">criticalValue</span><span style="color: #0000FF;">+</span><span style="color: #000000;">id</span><span style="color: #0000FF;">*</span><span style="color: #000000;">3</span><span style="color: #0000FF;">)/</span><span style="color: #000000;">2</span><span style="color: #0000FF;">)</span>
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"Thread %d changed the critical value from %2d (+3*%d=%2d)/2 to %d\n"</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">id</span><span style="color: #0000FF;">,</span><span style="color: #000000;">pcv</span><span style="color: #0000FF;">,</span><span style="color: #000000;">id</span><span style="color: #0000FF;">,</span><span style="color: #000000;">pcv</span><span style="color: #0000FF;">+</span><span style="color: #000000;">3</span><span style="color: #0000FF;">*</span><span style="color: #000000;">id</span><span style="color: #0000FF;">,</span><span style="color: #000000;">criticalValue</span><span style="color: #0000FF;">})</span>
<span style="color: #000080;font-style:italic;">// end critical section
// exit protocol</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">t</span><span style="color: #0000FF;">=</span><span style="color: #000000;">id</span><span style="color: #0000FF;">+</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">nthreads</span> <span style="color: #008080;">do</span> <span style="color: #000080;font-style:italic;">// Ensure everyone in the waiting room has</span>
<span style="color: #008080;">while</span> <span style="color: #008080;">not</span> <span style="color: #000000;">all_others</span><span style="color: #0000FF;">(</span><span style="color: #000000;">id</span><span style="color: #0000FF;">,</span><span style="color: #000000;">in014</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span> <span style="color: #000080;font-style:italic;">// realized door is supposed to be closed</span>
<span style="color: #7060A8;">sleep</span><span style="color: #0000FF;">(</span><span style="color: #000000;">0.01</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">while</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #000000;">flags</span><span style="color: #0000FF;">[</span><span style="color: #000000;">id</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span> <span style="color: #000080;font-style:italic;">// Leave. Reopen door if nobody is still
// in the waiting room</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">procedure</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">threads</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">repeat</span><span style="color: #0000FF;">(</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">nthreads</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">id</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">nthreads</span> <span style="color: #008080;">do</span>
<span style="color: #000000;">threads</span><span style="color: #0000FF;">[</span><span style="color: #000000;">id</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">create_thread</span><span style="color: #0000FF;">(</span><span style="color: #000000;">runSzymanski</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">id</span><span style="color: #0000FF;">},</span><span style="color: #000000;">CREATE_SUSPENDED</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">id</span> <span style="color: #008080;">in</span> <span style="color: #7060A8;">shuffle</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">tagset</span><span style="color: #0000FF;">(</span><span style="color: #000000;">nthreads</span><span style="color: #0000FF;">))</span> <span style="color: #008080;">do</span>
<span style="color: #7060A8;">resume_thread</span><span style="color: #0000FF;">(</span><span style="color: #000000;">threads</span><span style="color: #0000FF;">[</span><span style="color: #000000;">id</span><span style="color: #0000FF;">])</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #000080;font-style:italic;">-- NB: do not terminate main thread before all subthreads are done!</span>
<span style="color: #7060A8;">wait_thread</span><span style="color: #0000FF;">(</span><span style="color: #000000;">threads</span><span style="color: #0000FF;">)</span>
<!--</syntaxhighlight>-->
{{out}}
Different every time, of course.
<pre>
Thread 4 changed the critical value from 1 (+3*4=13)/2 to 6
Thread 6 changed the critical value from 6 (+3*6=24)/2 to 12
Thread 2 changed the critical value from 12 (+3*2=18)/2 to 9
Thread 1 changed the critical value from 9 (+3*1=12)/2 to 6
Thread 5 changed the critical value from 6 (+3*5=21)/2 to 10
Thread 3 changed the critical value from 10 (+3*3=19)/2 to 9
</pre>
 
=={{header|Raku}}==
<syntaxhighlight lang="raku" line># 20230822 Raku programming solution
 
use OO::Monitors;
 
my \N = 10;
 
monitor Szymański {
 
has @.tasks;
my $critical = 0;
 
method runSzymański($id) {
@.tasks[$id] = 1;
( my @others = @.tasks ).splice: $id,1;
until @others.all ~~ 0|1|2 { $*THREAD.yield }
@.tasks[$id] = 3;
if @others.any ~~ 1 {
@.tasks[$id] = 2;
until @others.any ~~ 4 { $*THREAD.yield }
}
@.tasks[$id] = 4;
until @.tasks[^$id].all ~~ 0|1 { $*THREAD.yield }
$critical = ((my $previous = $critical) + $id * 3) div 2;
say "Thread $id changed the critical value from $previous to $critical";
until @.tasks[$id^..*-1].all ~~ 0|1|4 { $*THREAD.yield }
@.tasks[$id] = 0
}
}
 
my $flag = Szymański.new: tasks => 0 xx N;
await Promise.allof( ^N .pick(*).map: { start { $flag.runSzymański: $_ } } );</syntaxhighlight>
{{out}}
<pre>Thread 6 changed the critical value from 0 to 9
Thread 1 changed the critical value from 9 to 6
Thread 5 changed the critical value from 6 to 10
Thread 4 changed the critical value from 10 to 11
Thread 7 changed the critical value from 11 to 16
Thread 9 changed the critical value from 16 to 21
Thread 8 changed the critical value from 21 to 22
Thread 3 changed the critical value from 22 to 15
Thread 2 changed the critical value from 15 to 10
Thread 0 changed the critical value from 10 to 5</pre>
 
=={{header|Wren}}==
{{trans|Julia}}
 
Although Wren-CLI can spawn any number of fibers, the VM is single threaded and so only one fiber can run at a time. Consequently, there is never a need to lock a shared resource.
 
Also fibers are cooperatively scheduled and don't use OS threads so we never have to worry about context switches taking place.
 
The best we can do here is therefore to simulate Szymański's algorithm by randomizing the order in which the fibers start so that the output is not completely deterministic.
 
As Wren fibers don't have an id property, we pass one as an argument when starting the fiber.
<syntaxhighlight lang="wren">import "random" for Random
 
var rand = Random.new()
 
var flag = {}
 
var allszy = (1..6).toList
 
var criticalValue = 1
 
var runSzymanski = Fn.new { |id|
var others = allszy.where { |t| t != id }.toList
flag[id] = 1 // Standing outside waiting room
while (!others.all { |t| flag[t] < 3}) { // Wait for open door
Fiber.yield()
}
flag[id] = 3 // Standing in doorway
if (others.any { |t| flag[t] == 1 }) { // Another fiber is waiting to enter
flag[id] = 2 // Waiting for other fibers to enter
while (!others.any { |t| flag[t] == 4 }) { // Wait for a fiber to enter & close door
Fiber.yield()
}
}
flag[id] = 4 // The door is closed
for (t in others) { // Wait for everyone of lower id to exit
if (t >= id) continue
while (flag[t] > 1) Fiber.yield()
}
 
// critical section
criticalValue = criticalValue + id * 3
criticalValue = (criticalValue/2).floor
System.print("Fiber %(id) changed the critical value to %(criticalValue).")
// end critical section
 
// exit protocol
for (t in others) { // Ensure everyone in the waiting room has
if (t <= id) continue // realized door is supposed to be closed
while (![0, 1, 4].contains(flag[t])) {
Fiber.yield()
}
}
flag[id] = 0 // Leave. Reopen door if nobody is still
// in the waiting room
}
 
var testSzymanski = Fn.new {
var fibers = List.filled(6, 0)
for (id in 1..6) {
fibers[id-1] = Fiber.new(runSzymanski)
flag[id] = 0
}
rand.shuffle(allszy)
for (id in allszy) {
fibers[id-1].call(id)
}
}
 
testSzymanski.call()</syntaxhighlight>
 
{{out}}
Sample output:
<pre>
Fiber 4 changed the critical value to 6.
Fiber 3 changed the critical value to 7.
Fiber 6 changed the critical value to 12.
Fiber 1 changed the critical value to 7.
Fiber 5 changed the critical value to 11.
Fiber 2 changed the critical value to 8.
</pre>
9,486

edits