aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorlukechampine <luke.champine@gmail.com>2016-03-30 20:56:16 -0400
committerlukechampine <luke.champine@gmail.com>2016-03-30 21:12:54 -0400
commitc9d7615f70528c40eec6aa95059ba24afd24f239 (patch)
tree6677004153fd62bb5af61ba858ff9b6ab7eaa750
parentclarify caveat (diff)
downloadstm-c9d7615f70528c40eec6aa95059ba24afd24f239.tar.gz
stm-c9d7615f70528c40eec6aa95059ba24afd24f239.tar.xz
efficient retries via sync.Cond
-rw-r--r--stm.go13
1 files changed, 13 insertions, 0 deletions
diff --git a/stm.go b/stm.go
index 148a404..e0c60a4 100644
--- a/stm.go
+++ b/stm.go
@@ -88,6 +88,7 @@ const Retry = "retry"
// The globalLock serializes transaction verification/committal.
var globalLock sync.Mutex
+var globalCond = sync.NewCond(&globalLock)
// A Var holds an STM variable.
type Var struct {
@@ -126,6 +127,15 @@ func (tx *Tx) commit() {
}
}
+// wait blocks until another transaction modifies any of the Vars read by tx.
+func (tx *Tx) wait() {
+ globalCond.L.Lock()
+ for tx.verify() {
+ globalCond.Wait()
+ }
+ globalCond.L.Unlock()
+}
+
// Get returns the value of v as of the start of the transaction.
func (tx *Tx) Get(v *Var) interface{} {
// If we previously wrote to v, it will be in the write log.
@@ -200,6 +210,7 @@ retry:
writes: make(map[*Var]interface{}),
}
if catchRetry(fn, tx) {
+ tx.wait()
goto retry
}
// verify the read log
@@ -210,6 +221,7 @@ retry:
}
// commit the write log
tx.commit()
+ globalCond.Broadcast()
globalLock.Unlock()
}
@@ -227,6 +239,7 @@ func AtomicSet(v *Var, val interface{}) {
// since we're only doing one operation, we don't need a full transaction
globalLock.Lock()
v.val.Store(val)
+ globalCond.Broadcast()
globalLock.Unlock()
}