Skip to content

Commit

Permalink
Protect the shared value for concurrent access
Browse files Browse the repository at this point in the history
  • Loading branch information
janos committed Dec 5, 2023
1 parent a3a78ab commit a7affac
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 1 deletion.
3 changes: 2 additions & 1 deletion singleflight.go
Original file line number Diff line number Diff line change
Expand Up @@ -82,8 +82,9 @@ func (g *Group[K, V]) wait(ctx context.Context, key K, c *call[V]) (v V, shared
c.cancel()
delete(g.calls, key)
}
shared = c.shared
g.mu.Unlock()
return v, c.shared, err
return v, shared, err
}

// Forget tells the singleflight to forget about a key. Future calls
Expand Down
28 changes: 28 additions & 0 deletions singleflight_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,34 @@ func TestDo(t *testing.T) {
}
}

func TestDo_concurrentAccess(t *testing.T) {
var g singleflight.Group[string, string]

want := "val"
key := "key"
var wg sync.WaitGroup
n := 100

wg.Add(n)
for i := 0; i < n; i++ {
go func(i int) {
defer wg.Done()
got, shared, err := g.Do(context.Background(), key, func(_ context.Context) (string, error) {
return want, nil
})
if err != nil {
t.Error(err)
}
_ = shared // read the shared to test the concurrent access
if got != want {
t.Errorf("got value %v, want %v", got, want)
}
time.Sleep(5 * time.Millisecond)
}(i)
}
wg.Wait()
}

func TestDo_error(t *testing.T) {
var g singleflight.Group[string, string]
wantErr := errors.New("test error")
Expand Down

0 comments on commit a7affac

Please sign in to comment.