Skip to content

Commit 64c90ed

Browse files
committed
fix(sync/singleflight): api enhance
1 parent 1139656 commit 64c90ed

File tree

2 files changed

+28
-18
lines changed

2 files changed

+28
-18
lines changed

sync/singleflight/singleflight.go

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ type call[V any] struct {
6969
}
7070

7171
type Group[K comparable] struct {
72-
g Group2[K, struct{}]
72+
g GroupValue[K, struct{}]
7373
}
7474

7575
func (g *Group[K]) Do(key K, fn func() error) (error, bool) {
@@ -79,13 +79,19 @@ func (g *Group[K]) Do(key K, fn func() error) (error, bool) {
7979
return err, shared
8080
}
8181

82+
func (g *Group[K]) DoChan(key K, fn func() error) <-chan Result[struct{}] {
83+
return g.g.DoChan(key, func() (struct{}, error) {
84+
return struct{}{}, fn()
85+
})
86+
}
87+
8288
func (g *Group[K]) Forget(key K) {
8389
g.g.Forget(key)
8490
}
8591

86-
// Group2 represents a class of work and forms a namespace in
92+
// GroupValue represents a class of work and forms a namespace in
8793
// which units of work can be executed with duplicate suppression.
88-
type Group2[K comparable, V any] struct {
94+
type GroupValue[K comparable, V any] struct {
8995
mu sync.Mutex // protects m
9096
m map[K]*call[V] // lazily initialized
9197
}
@@ -103,7 +109,7 @@ type Result[V any] struct {
103109
// time. If a duplicate comes in, the duplicate caller waits for the
104110
// original to complete and receives the same results.
105111
// The return value shared indicates whether v was given to multiple callers.
106-
func (g *Group2[K, V]) Do(key K, fn func() (V, error)) (v V, err error, shared bool) {
112+
func (g *GroupValue[K, V]) Do(key K, fn func() (V, error)) (v V, err error, shared bool) {
107113
g.mu.Lock()
108114
if g.m == nil {
109115
g.m = make(map[K]*call[V])
@@ -133,7 +139,7 @@ func (g *Group2[K, V]) Do(key K, fn func() (V, error)) (v V, err error, shared b
133139
// results when they are ready.
134140
//
135141
// The returned channel will not be closed.
136-
func (g *Group2[K, V]) DoChan(key K, fn func() (V, error)) <-chan Result[V] {
142+
func (g *GroupValue[K, V]) DoChan(key K, fn func() (V, error)) <-chan Result[V] {
137143
ch := make(chan Result[V], 1)
138144
g.mu.Lock()
139145
if g.m == nil {
@@ -156,7 +162,7 @@ func (g *Group2[K, V]) DoChan(key K, fn func() (V, error)) <-chan Result[V] {
156162
}
157163

158164
// doCall handles the single call for a key.
159-
func (g *Group2[K, V]) doCall(c *call[V], key K, fn func() (V, error)) {
165+
func (g *GroupValue[K, V]) doCall(c *call[V], key K, fn func() (V, error)) {
160166
normalReturn := false
161167
recovered := false
162168

@@ -222,8 +228,12 @@ func (g *Group2[K, V]) doCall(c *call[V], key K, fn func() (V, error)) {
222228
// Forget tells the singleflight to forget about a key. Future calls
223229
// to Do for this key will call the function rather than waiting for
224230
// an earlier call to complete.
225-
func (g *Group2[K, V]) Forget(key K) {
231+
func (g *GroupValue[K, V]) Forget(key K) {
226232
g.mu.Lock()
227233
delete(g.m, key)
228234
g.mu.Unlock()
229235
}
236+
237+
// Group2
238+
// Deprecated use GroupValue instead
239+
type Group2[K comparable, V any] = GroupValue[K, V]

sync/singleflight/singleflight_test.go

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ func TestPanicErrorUnwrap(t *testing.T) {
5353

5454
var recovered interface{}
5555

56-
group := &Group2[string, string]{}
56+
group := &GroupValue[string, string]{}
5757

5858
func() {
5959
defer func() {
@@ -83,7 +83,7 @@ func TestPanicErrorUnwrap(t *testing.T) {
8383
}
8484

8585
func TestDo(t *testing.T) {
86-
var g Group2[string, string]
86+
var g GroupValue[string, string]
8787
v, err, _ := g.Do("key", func() (string, error) {
8888
return "bar", nil
8989
})
@@ -96,7 +96,7 @@ func TestDo(t *testing.T) {
9696
}
9797

9898
func TestDoErr(t *testing.T) {
99-
var g Group2[string, string]
99+
var g GroupValue[string, string]
100100
someErr := errors.New("Some error")
101101
v, err, _ := g.Do("key", func() (string, error) {
102102
return "", someErr
@@ -110,7 +110,7 @@ func TestDoErr(t *testing.T) {
110110
}
111111

112112
func TestDoDupSuppress(t *testing.T) {
113-
var g Group2[string, string]
113+
var g GroupValue[string, string]
114114
var wg1, wg2 sync.WaitGroup
115115
c := make(chan string, 1)
116116
var calls int32
@@ -158,7 +158,7 @@ func TestDoDupSuppress(t *testing.T) {
158158
// Test that singleflight behaves correctly after Forget called.
159159
// See https://github.com/golang/go/issues/31420
160160
func TestForget(t *testing.T) {
161-
var g Group2[string, int]
161+
var g GroupValue[string, int]
162162

163163
var (
164164
firstStarted = make(chan struct{})
@@ -199,7 +199,7 @@ func TestForget(t *testing.T) {
199199
}
200200

201201
func TestDoChan(t *testing.T) {
202-
var g Group2[string, string]
202+
var g GroupValue[string, string]
203203
ch := g.DoChan("key", func() (string, error) {
204204
return "bar", nil
205205
})
@@ -218,7 +218,7 @@ func TestDoChan(t *testing.T) {
218218
// Test singleflight behaves correctly after Do panic.
219219
// See https://github.com/golang/go/issues/41133
220220
func TestPanicDo(t *testing.T) {
221-
var g Group2[string, string]
221+
var g GroupValue[string, string]
222222
fn := func() (string, error) {
223223
panic("invalid memory address or nil pointer dereference")
224224
}
@@ -255,7 +255,7 @@ func TestPanicDo(t *testing.T) {
255255
}
256256

257257
func TestGoexitDo(t *testing.T) {
258-
var g Group2[string, string]
258+
var g GroupValue[string, string]
259259
fn := func() (string, error) {
260260
runtime.Goexit()
261261
return "", nil
@@ -309,7 +309,7 @@ func TestPanicDoChan(t *testing.T) {
309309
recover()
310310
}()
311311

312-
g := new(Group2[string, string])
312+
g := new(GroupValue[string, string])
313313
ch := g.DoChan("", func() (string, error) {
314314
panic("Panicking in DoChan")
315315
})
@@ -346,7 +346,7 @@ func TestPanicDoSharedByDoChan(t *testing.T) {
346346
blocked := make(chan struct{})
347347
unblock := make(chan struct{})
348348

349-
g := new(Group2[string, string])
349+
g := new(GroupValue[string, string])
350350
go func() {
351351
defer func() {
352352
recover()
@@ -392,7 +392,7 @@ func TestPanicDoSharedByDoChan(t *testing.T) {
392392
}
393393

394394
func ExampleGroup() {
395-
g := new(Group2[string, string])
395+
g := new(GroupValue[string, string])
396396

397397
block := make(chan struct{})
398398
res1c := g.DoChan("key", func() (string, error) {

0 commit comments

Comments
 (0)