aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README.md82
-rw-r--r--doc_test.go77
2 files changed, 83 insertions, 76 deletions
diff --git a/README.md b/README.md
index 849897d..6330f79 100644
--- a/README.md
+++ b/README.md
@@ -29,86 +29,15 @@ applications in Go. If you find this package useful, please tell us about it!
## Examples
-Note that `Operation` now returns a value of type `interface{}`, which isn't included in the examples
-throughout the documentation yet. See the type signatures for `Atomically` and `Operation`.
-
-Here's some example code that demonstrates how to perform common operations:
-
-```go
-// create a shared variable
-n := stm.NewVar(3)
-
-// read a variable
-var v int
-stm.Atomically(func(tx *stm.Tx) {
- v = tx.Get(n).(int)
-})
-// or:
-v = stm.AtomicGet(n).(int)
-
-// write to a variable
-stm.Atomically(func(tx *stm.Tx) {
- tx.Set(n, 12)
-})
-// or:
-stm.AtomicSet(n, 12)
-
-// update a variable
-stm.Atomically(func(tx *stm.Tx) {
- cur := tx.Get(n).(int)
- tx.Set(n, cur-1)
-})
-
-// block until a condition is met
-stm.Atomically(func(tx *stm.Tx) {
- cur := tx.Get(n).(int)
- if cur != 0 {
- tx.Retry()
- }
- tx.Set(n, 10)
-})
-// or:
-stm.Atomically(func(tx *stm.Tx) {
- cur := tx.Get(n).(int)
- tx.Assert(cur == 0)
- tx.Set(n, 10)
-})
-
-// select among multiple (potentially blocking) transactions
-stm.Atomically(stm.Select(
- // this function blocks forever, so it will be skipped
- func(tx *stm.Tx) { tx.Retry() },
-
- // this function will always succeed without blocking
- func(tx *stm.Tx) { tx.Set(n, 10) },
-
- // this function will never run, because the previous
- // function succeeded
- func(tx *stm.Tx) { tx.Set(n, 11) },
-))
-
-// since Select is a normal transaction, if the entire select retries
-// (blocks), it will be retried as a whole:
-x := 0
-stm.Atomically(stm.Select(
- // this function will run twice, and succeed the second time
- func(tx *stm.Tx) { tx.Assert(x == 1) },
-
- // this function will run once
- func(tx *stm.Tx) {
- x = 1
- tx.Retry()
- },
-))
-// But wait! Transactions are only retried when one of the Vars they read is
-// updated. Since x isn't a stm Var, this code will actually block forever --
-// but you get the idea.
-```
+See the package examples in the Go package docs for examples of common operations.
See [example_santa_test.go](example_santa_test.go) for a more complex example.
## Pointers
+Note that `Operation` now returns a value of type `interface{}`, which isn't included in the
+examples throughout the documentation yet. See the type signatures for `Atomically` and `Operation`.
+
Be very careful when managing pointers inside transactions! (This includes
slices, maps, channels, and captured variables.) Here's why:
@@ -191,4 +120,5 @@ BenchmarkReadVarChannel-4 10000 240086 ns/op
## Credits
-Package stm was [originally](https://github.com/lukechampine/stm/issues/3#issuecomment-549087541) created by lukechampine.
+Package stm was [originally](https://github.com/lukechampine/stm/issues/3#issuecomment-549087541)
+created by lukechampine.
diff --git a/doc_test.go b/doc_test.go
new file mode 100644
index 0000000..f6bb863
--- /dev/null
+++ b/doc_test.go
@@ -0,0 +1,77 @@
+package stm_test
+
+import (
+ "github.com/anacrolix/stm"
+)
+
+func Example() {
+ // create a shared variable
+ n := stm.NewVar(3)
+
+ // read a variable
+ var v int
+ stm.Atomically(stm.VoidOperation(func(tx *stm.Tx) {
+ v = tx.Get(n).(int)
+ }))
+ // or:
+ v = stm.AtomicGet(n).(int)
+ _ = v
+
+ // write to a variable
+ stm.Atomically(stm.VoidOperation(func(tx *stm.Tx) {
+ tx.Set(n, 12)
+ }))
+ // or:
+ stm.AtomicSet(n, 12)
+
+ // update a variable
+ stm.Atomically(stm.VoidOperation(func(tx *stm.Tx) {
+ cur := tx.Get(n).(int)
+ tx.Set(n, cur-1)
+ }))
+
+ // block until a condition is met
+ stm.Atomically(stm.VoidOperation(func(tx *stm.Tx) {
+ cur := tx.Get(n).(int)
+ if cur != 0 {
+ tx.Retry()
+ }
+ tx.Set(n, 10)
+ }))
+ // or:
+ stm.Atomically(stm.VoidOperation(func(tx *stm.Tx) {
+ cur := tx.Get(n).(int)
+ tx.Assert(cur == 0)
+ tx.Set(n, 10)
+ }))
+
+ // select among multiple (potentially blocking) transactions
+ stm.Atomically(stm.Select(
+ // this function blocks forever, so it will be skipped
+ stm.VoidOperation(func(tx *stm.Tx) { tx.Retry() }),
+
+ // this function will always succeed without blocking
+ stm.VoidOperation(func(tx *stm.Tx) { tx.Set(n, 10) }),
+
+ // this function will never run, because the previous
+ // function succeeded
+ stm.VoidOperation(func(tx *stm.Tx) { tx.Set(n, 11) }),
+ ))
+
+ // since Select is a normal transaction, if the entire select retries
+ // (blocks), it will be retried as a whole:
+ x := 0
+ stm.Atomically(stm.Select(
+ // this function will run twice, and succeed the second time
+ stm.VoidOperation(func(tx *stm.Tx) { tx.Assert(x == 1) }),
+
+ // this function will run once
+ stm.VoidOperation(func(tx *stm.Tx) {
+ x = 1
+ tx.Retry()
+ }),
+ ))
+ // But wait! Transactions are only retried when one of the Vars they read is
+ // updated. Since x isn't a stm Var, this code will actually block forever --
+ // but you get the idea.
+}