RosettaCodeData/Task/Atomic-updates/Lasso/atomic-updates.lasso

77 lines
2.0 KiB
Plaintext

define atomic => thread {
data
private buckets = staticarray_join(10, void),
private lock = 0
public onCreate => {
loop(.buckets->size) => {
.`buckets`->get(loop_count) = math_random(0, 1000)
}
}
public buckets => .`buckets`
public bucket(index::integer) => .`buckets`->get(#index)
public transfer(source::integer, dest::integer, amount::integer) => {
#source == #dest
? return
#amount = math_min(#amount, .`buckets`->get(#source))
.`buckets`->get(#source) -= #amount
.`buckets`->get(#dest) += #amount
}
public numBuckets => .`buckets`->size
public lock => {
.`lock` == 1
? return false
.`lock` = 1
return true
}
public unlock => {
.`lock` = 0
}
}
local(initial_total) = (with b in atomic->buckets sum #b)
local(total) = #initial_total
// Make 2 buckets close to equal
local(_) = split_thread => {
local(bucket1) = math_random(1, atomic->numBuckets)
local(bucket2) = math_random(1, atomic->numBuckets)
local(value1) = atomic->bucket(#bucket1)
local(value2) = atomic->bucket(#bucket2)
if(#value1 >= #value2) => {
atomic->transfer(#bucket1, #bucket2, (#value1 - #value2) / 2)
else
atomic->transfer(#bucket2, #bucket1, (#value2 - #value1) / 2)
}
currentCapture->restart
}
// Randomly distribute 2 buckets
local(_) = split_thread => {
local(bucket1) = math_random(1, atomic->numBuckets)
local(bucket2) = math_random(1, atomic->numBuckets)
local(value1) = atomic->bucket(#bucket1)
atomic->transfer(#bucket1, #bucket2, math_random(1, #value1))
currentCapture->restart
}
local(buckets)
while(#initial_total == #total) => {
sleep(2000)
#buckets = atomic->buckets
#total = with b in #buckets sum #b
stdoutnl(#buckets->asString + " -- total: " + #total)
}
stdoutnl(`ERROR: totals no longer match: ` + #initial_total + ', ' + #total)