aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--stm.go6
-rw-r--r--stm_test.go19
2 files changed, 24 insertions, 1 deletions
diff --git a/stm.go b/stm.go
index fc4a125..24e0e18 100644
--- a/stm.go
+++ b/stm.go
@@ -231,7 +231,11 @@ func AtomicGet(v *Var) interface{} {
func AtomicSet(v *Var, val interface{}) {
// since we're only doing one operation, we don't need a full transaction
globalLock.Lock()
- (&Tx{writes: map[*Var]interface{}{v: val}}).commit()
+ v.mu.Lock()
+ v.val = val
+ v.version++
+ v.mu.Unlock()
+ globalCond.Broadcast()
globalLock.Unlock()
}
diff --git a/stm_test.go b/stm_test.go
index b6ecb16..1b1b737 100644
--- a/stm_test.go
+++ b/stm_test.go
@@ -199,6 +199,25 @@ func TestReadWritten(t *testing.T) {
})
}
+func TestAtomicSetRetry(t *testing.T) {
+ // AtomicSet should cause waiting transactions to retry
+ x := NewVar(3)
+ done := make(chan struct{})
+ go func() {
+ Atomically(func(tx *Tx) {
+ tx.Assert(tx.Get(x).(int) == 5)
+ })
+ done <- struct{}{}
+ }()
+ time.Sleep(10 * time.Millisecond)
+ AtomicSet(x, 5)
+ select {
+ case <-done:
+ case <-time.After(time.Second):
+ t.Fatal("AtomicSet did not wake up a waiting transaction")
+ }
+}
+
func BenchmarkAtomicGet(b *testing.B) {
x := NewVar(0)
for i := 0; i < b.N; i++ {