data TVar
A transactional variable holding a T. A cheap handle: clone() shares the variable; it may live in a static and be
used from any task.
Example:
use std.stm { TVar }
fn main() io {
let from = TVar<i64>.new(100)
let to = TVar<i64>.new(0)
atomic {
from.set(from.get() - 30)
to.set(to.get() + 30)
}
print("{atomic { from.get() }} {atomic { to.get() }}")
}Вывод
70 30
Примеры#
Рецепты STM: update и ожидание условия через check.
Счётчик и ожидание#
Десять задач увеличивают общий счётчик в транзакциях без блокировок; ещё одна ждёт флага через check и читает итог.
use std.stm { TVar, check }
static COUNTER: TVar<i64> = TVar(0)
static READY: TVar<bool> = TVar(false)
fn bump() {
atomic { COUNTER.update(x => x + 1) } // update читает и пишет в одной транзакции
}
fn waiter() -> i64 {
atomic {
check(READY.get()) // ждёт, пока READY станет true
COUNTER.get()
}
}
fn main() io, time {
let total = scope {
let w = spawn waiter()
for _ in 0..10 { _ = spawn bump() }
sleep(20ms)
atomic { READY.set(true) }
w.join()!
}
print("{total}")
}Вывод
10
@builtin("TVar") pub(api) data TVar<T>Потокобезопасность. transactional: concurrent `atomic` blocks over the same variables are serialized and retried on conflict.
С версии. 1.0.0-beta
Методы
new | (value: T) -> SelfA new variable with the initial value value. |
get | () -> TThe value (a copy) as seen by the running transaction. |
set | (value: T)Replaces the value when the transaction commits. |
update | (f: fn(T) -> T)set(f(get())). |
swap | (value: T) -> TSets the value and returns the previous one. |
clone | () -> TVar<T>Another handle of the same variable. |
Определено в: std/stm/stm.oxl:59