Onyx may use a strong memory model instead, ensuring the sequential consistency.
In short, memory operations would execute in the way they're printed in source files, without any optimisations.
The following code would be guaranteed to always output either Ready 42
or Not ready
with the strong memory model:
ready = false
x = 0
async do
x = 42
ready = true
end
async do
if ready
puts "Ready"
puts x
else
puts "Not ready"
end
end
sleep
As a trade-off, the performance would be poor by default. It would be possible, though,
to explicitly disable strict ordering to allow the optimizer to do its work.
The unordered
block would allow the compiler to freely reorder any memory operations within the block.
ready = false
x = 0
async do
# May lead to the `Ready 0` output, if the operations got reordered!
unordered do
x = 42
ready = true
end
end
async do
if ready
puts "Ready"
puts x
else
puts "Not ready"
end
end
sleep
It would also be possible to use memory fences and atomics within the unordered
block,
so the output would be guaranteed to be either Ready 42
or Not ready
, again.
async do
unordered do
x = 42
fence(:release)
ready = true
end
end
ready = Atomic(false)
async do
unordered do
x = 42
ready.set(true, :release)
end
end
async do
unordered do
is_ready = ready.get(:acquire)
the_x = x
end
if is_ready
puts "Ready"
puts the_x
else
puts "Not ready"
end
end