1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
|
package stm
import (
g "gobang"
)
func MainTest() {
g.TestStart("Example of API usage")
g.Testing("operating on int variables", func() {
// create a shared variable
n := NewVar(3)
// read a variable
var v int
Atomically(VoidOperation(func(tx *Tx) {
v = n.Get(tx)
}))
g.TAssertEqual(v, 3)
// or:
v = Deref(n)
g.TAssertEqual(v, 3)
// write to a variable
Atomically(VoidOperation(func(tx *Tx) {
n.Set(tx, 12)
}))
g.TAssertEqual(Deref(n), 12)
// or:
AtomicSet(n, 11)
g.TAssertEqual(Deref(n), 11)
// update a variable
Atomically(VoidOperation(func(tx *Tx) {
cur := n.Get(tx)
n.Set(tx, cur+1)
}))
g.TAssertEqual(Deref(n), 12)
// block until a condition is met
Atomically(VoidOperation(func(tx *Tx) {
cur := n.Get(tx)
if cur == 0 {
tx.Retry()
}
n.Set(tx, 10)
}))
g.TAssertEqual(Deref(n), 10)
// or:
Atomically(VoidOperation(func(tx *Tx) {
cur := n.Get(tx)
tx.Assert(cur != 0)
n.Set(tx, 11)
}))
g.TAssertEqual(Deref(n), 11)
// select among multiple (potentially blocking) transactions
Atomically(Select(
// this function blocks forever, so it will be skipped
VoidOperation(func(tx *Tx) { tx.Retry() }),
// this function will always succeed without blocking
VoidOperation(func(tx *Tx) { n.Set(tx, 10) }),
// this function will never run, because the previous
// function succeeded
VoidOperation(func(tx *Tx) { n.Set(tx, 11) }),
))
g.TAssertEqual(Deref(n), 10)
})
}
|