diff options
author | lukechampine <luke.champine@gmail.com> | 2016-03-30 20:56:16 -0400 |
---|---|---|
committer | lukechampine <luke.champine@gmail.com> | 2016-03-30 21:12:54 -0400 |
commit | c9d7615f70528c40eec6aa95059ba24afd24f239 (patch) | |
tree | 6677004153fd62bb5af61ba858ff9b6ab7eaa750 | |
parent | clarify caveat (diff) | |
download | stm-c9d7615f70528c40eec6aa95059ba24afd24f239.tar.gz stm-c9d7615f70528c40eec6aa95059ba24afd24f239.tar.xz |
efficient retries via sync.Cond
-rw-r--r-- | stm.go | 13 |
1 files changed, 13 insertions, 0 deletions
@@ -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() } |