RosettaCodeData/Task/Atomic-updates/Smalltalk/atomic-updates.st

69 lines
2.0 KiB
Smalltalk

NUM_BUCKETS := 10.
"create and preset with random data"
buckets := (1 to:NUM_BUCKETS)
collect:[:i | Random nextIntegerBetween:0 and:10000]
as:Array.
count_randomizations := 0.
count_equalizations := 0.
printSum :=
[
"the sum must be computed and printed while noone fiddles around"
|snapshot|
snapshot := buckets synchronized:[ buckets copy ].
Transcript showCR: e' {snapshot} sum={snapshot sum}'.
].
pickTwo :=
[:action |
"pick two pockets and eval action on it"
|p1 p2|
p1 := Random nextIntegerBetween:1 and:NUM_BUCKETS.
p2 := Random nextIntegerBetween:1 and:NUM_BUCKETS.
buckets synchronized:[ action value:p1 value:p2 ].
].
randomize :=
[
pickTwo value:[:p1 :p2 |
"take a random value from p1 and add to p2"
|howMuch|
howMuch := Random nextIntegerBetween:0 and:(buckets at:p1).
buckets at:p1 put:(buckets at:p1)-howMuch.
buckets at:p2 put:(buckets at:p2)+howMuch.
].
count_randomizations := count_randomizations + 1.
].
equalize :=
[
pickTwo value:[:p1 :p2 |
"average them"
|diff|
diff := ((buckets at:p1) - (buckets at:p2)) // 2.
buckets at:p1 put:(buckets at:p1)-diff.
buckets at:p2 put:(buckets at:p2)+diff.
].
count_equalizations := count_equalizations + 1.
].
"start the show"
randomizer := [ randomize loop ] fork.
equalizer := [ equalize loop ] fork.
"every 2 seconds, print the sum"
monitor := [
[
printSum value.
Delay waitFor:2 seconds.
] loop.
] fork.
"let it run for 10 seconds, then kill them all"
Delay waitFor:20 seconds.
randomizer terminate.
equalizer terminate.
monitor terminate.
Stdout printCR: e'performed {count_equalizations} equalizations and {count_randomizations} randomizations'.