aboutsummaryrefslogtreecommitdiff
path: root/funcs.go
diff options
context:
space:
mode:
Diffstat (limited to 'funcs.go')
-rw-r--r--funcs.go26
1 files changed, 22 insertions, 4 deletions
diff --git a/funcs.go b/funcs.go
index 7b5df38..4967e83 100644
--- a/funcs.go
+++ b/funcs.go
@@ -1,7 +1,7 @@
package stm
// Atomically executes the atomic function fn.
-func Atomically(fn func(*Tx)) {
+func Atomically(fn func(*Tx)) interface{} {
retry:
// run the transaction
tx := &Tx{
@@ -9,9 +9,26 @@ retry:
writes: make(map[*Var]interface{}),
}
tx.cond.L = &globalLock
- if catchRetry(fn, tx) {
- // wait for one of the variables we read to change before retrying
- tx.wait()
+ var ret interface{}
+ if func() (retry bool) {
+ defer func() {
+ r := recover()
+ if r == nil {
+ return
+ }
+ if _ret, ok := r.(_return); ok {
+ ret = _ret.value
+ } else if r == Retry {
+ // wait for one of the variables we read to change before retrying
+ tx.wait()
+ retry = true
+ } else {
+ panic(r)
+ }
+ }()
+ fn(tx)
+ return false
+ }() {
goto retry
}
// verify the read log
@@ -23,6 +40,7 @@ retry:
// commit the write log and broadcast that variables have changed
tx.commit()
globalLock.Unlock()
+ return ret
}
// AtomicGet is a helper function that atomically reads a value.