From c35a2c748c6ad053344c9f15f6f86246e48628e0 Mon Sep 17 00:00:00 2001 From: Matt Joiner Date: Fri, 2 Oct 2020 17:35:11 +1000 Subject: Only wake Tx if they're still reading a modified value --- funcs.go | 2 ++ tx.go | 2 ++ var.go | 8 +++++--- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/funcs.go b/funcs.go index 91d6bc8..80c25b1 100644 --- a/funcs.go +++ b/funcs.go @@ -71,7 +71,9 @@ retry: time.Sleep(time.Duration(ns)) } } + tx.mu.Lock() ret, retry := catchRetry(op, tx) + tx.mu.Unlock() if retry { expvars.Add("retries", 1) // wait for one of the variables we read to change before retrying diff --git a/tx.go b/tx.go index 3a1506c..c064f76 100644 --- a/tx.go +++ b/tx.go @@ -121,12 +121,14 @@ func (tx *Tx) Assert(p bool) { } func (tx *Tx) reset() { + tx.mu.Lock() for k := range tx.reads { delete(tx.reads, k) } for k := range tx.writes { delete(tx.writes, k) } + tx.mu.Unlock() tx.removeRetryProfiles() tx.resetLocks() } diff --git a/var.go b/var.go index f3b8d40..3f43096 100644 --- a/var.go +++ b/var.go @@ -27,9 +27,11 @@ func (v *Var) wakeWatchers(new VarValue) { // We have to lock here to ensure that the Tx is waiting before we signal it. Otherwise we // could signal it before it goes to sleep and it will miss the notification. tx.mu.Lock() - tx.cond.Broadcast() - for !tx.waiting && !tx.completed { - tx.cond.Wait() + if read := tx.reads[v]; read != nil && read.Changed(new) { + tx.cond.Broadcast() + for !tx.waiting && !tx.completed { + tx.cond.Wait() + } } tx.mu.Unlock() return !v.value.Load().(VarValue).Changed(new) -- cgit v1.2.3