From 877bf18b7e26a4ee958fa4839c185c87fbcd7560 Mon Sep 17 00:00:00 2001 From: Matt Joiner Date: Fri, 2 Oct 2020 17:33:20 +1000 Subject: Add retry profiling --- tx.go | 42 ++++++++++++++++++++++++++++++------------ 1 file changed, 30 insertions(+), 12 deletions(-) (limited to 'tx.go') diff --git a/tx.go b/tx.go index 065cb6c..3a1506c 100644 --- a/tx.go +++ b/tx.go @@ -9,15 +9,16 @@ import ( // A Tx represents an atomic transaction. type Tx struct { - reads map[*Var]VarValue - writes map[*Var]interface{} - watching map[*Var]struct{} - locks txLocks - mu sync.Mutex - cond sync.Cond - waiting bool - completed bool - tries int + reads map[*Var]VarValue + writes map[*Var]interface{} + watching map[*Var]struct{} + locks txLocks + mu sync.Mutex + cond sync.Cond + waiting bool + completed bool + tries int + numRetryValues int } // Check that none of the logged values have changed since the transaction began. @@ -97,9 +98,18 @@ func (tx *Tx) Set(v *Var, val interface{}) { tx.writes[v] = val } -// Retry aborts the transaction and retries it when a Var changes. -func (tx *Tx) Retry() { - panic(Retry) +type txProfileValue struct { + *Tx + int +} + +// Retry aborts the transaction and retries it when a Var changes. You can return from this method +// to satisfy return values, but it should never actually return anything as it panics internally. +func (tx *Tx) Retry() interface{} { + retries.Add(txProfileValue{tx, tx.numRetryValues}, 0) + tx.numRetryValues++ + panic(retry) + panic("unreachable") } // Assert is a helper function that retries a transaction if the condition is @@ -117,9 +127,17 @@ func (tx *Tx) reset() { for k := range tx.writes { delete(tx.writes, k) } + tx.removeRetryProfiles() tx.resetLocks() } +func (tx *Tx) removeRetryProfiles() { + for tx.numRetryValues > 0 { + tx.numRetryValues-- + retries.Remove(txProfileValue{tx, tx.numRetryValues}) + } +} + func (tx *Tx) recycle() { for v := range tx.watching { delete(tx.watching, v) -- cgit v1.2.3