///|
/// Showcase for the STM library. Run with `moon run examples/showcase`
/// (add `--target native` for a native build).
async fn main {
// 1. An atomic transfer between two accounts: both writes commit together,
// and `check` retries the transaction while funds are insufficient.
let alice = @transaction.TVar::new(100)
let bob = @transaction.TVar::new(20)
@runner.atomically_async(txn => {
let funds = txn.read(alice)
txn.check(funds >= 30)
txn.write(alice, funds - 30)
txn.modify(bob, balance => balance + 30)
})
println("after transfer: alice=\{alice.peek()}, bob=\{bob.peek()}")
// 2. A consumer that parks on an empty queue until a producer commits,
// both tasks sharing the same transactional queue.
let jobs = @transaction.TQueue::new()
let results = @transaction.TVar::new([])
@aio.with_task_group(group => {
group.spawn_bg(() => {
for _ in 0..<3 {
let job = @runner.atomically_async(txn => jobs.pop(txn))
@runner.atomically_async(txn => {
txn.modify(results, done => {
let grown = done.copy()
grown.push(job * 10)
grown
})
})
}
})
for i in 1..<=3 {
@runner.atomically_async(txn => jobs.push(txn, i))
}
})
let rendered = StringBuilder()
for i, v in results.peek() {
if i > 0 {
rendered.write_string(", ")
}
rendered.write_string("\{v}")
}
println("consumer received: [\{rendered}]")
}