Szymański's algorithm: Difference between revisions

Added Wren
m (typo in text)
(Added Wren)
Line 87:
Thread 4 changed the critical value to 9.
Thread 6 changed the critical value to 13.
</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="ecmascript">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,476

edits