-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
da8b0cc
commit 8cf138c
Showing
7 changed files
with
248 additions
and
32 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
# Singleflight with Generics! | ||
|
||
[![GoDoc](https://godoc.org/github.com/brunomvsouza/singleflight?status.svg)](https://godoc.org/github.com/brunomvsouza/singleflight) | ||
|
||
> Package singleflight provides a duplicate function call suppression mechanism. | ||
This fork adds generics support (`Group[K comparable, V any]` and `Result[V any]`) to the original [x/sync/singleflight](https://golang.org/x/sync/singleflight) package. | ||
|
||
### Updates | ||
|
||
- I will keep this package up-to-date with the original one, at least until `x/sync/singleflight` adds support for generics. If you notice an update before I do, please open an issue or submit a pull request. | ||
- Versions will be tagged to align with the same versioning as the `x/sync/singleflight` package. | ||
|
||
### Usage | ||
|
||
For example usage, see: | ||
- [Group.Do](examples/Do/main.go) | ||
- [Group.DoChan](examples/DoChan/main.go) | ||
- [Group.DoForget](examples/Forget/main.go) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
// Copyright (c) 2023 Bruno Marques Venceslau de Souza. All rights reserved. | ||
// Use of this source code is governed by a BSD-style | ||
// license that can be found in the LICENSE file. | ||
|
||
package main | ||
|
||
import ( | ||
"fmt" | ||
"sync" | ||
"time" | ||
|
||
"github.com/brunomvsouza/singleflight" | ||
) | ||
|
||
func main() { | ||
var ( | ||
group singleflight.Group[string, string] | ||
wg sync.WaitGroup | ||
) | ||
|
||
wg.Add(2) | ||
|
||
go func() { | ||
defer wg.Done() | ||
res1, err1, shared1 := group.Do("key", func() (string, error) { | ||
time.Sleep(10 * time.Millisecond) | ||
return "func 1", nil | ||
}) | ||
fmt.Println("res1:", res1) | ||
fmt.Println("err1:", err1) | ||
fmt.Println("shared1:", shared1) | ||
}() | ||
|
||
go func() { | ||
defer wg.Done() | ||
res2, err2, shared2 := group.Do("key", func() (string, error) { | ||
time.Sleep(10 * time.Millisecond) | ||
return "func 2", nil | ||
}) | ||
fmt.Println("res2:", res2) | ||
fmt.Println("err2:", err2) | ||
fmt.Println("shared2:", shared2) | ||
}() | ||
|
||
wg.Wait() | ||
|
||
// Output: | ||
// res1: func 2 | ||
// err1: <nil> | ||
// res2: func 2 | ||
// err2: <nil> | ||
// shared2: true | ||
// shared1: true | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
// Copyright (c) 2023 Bruno Marques Venceslau de Souza. All rights reserved. | ||
// Use of this source code is governed by a BSD-style | ||
// license that can be found in the LICENSE file. | ||
|
||
// Copyright 2013 The Go Authors. All rights reserved. | ||
// Use of this source code is governed by a BSD-style | ||
// license that can be found in the LICENSE file. | ||
|
||
package main | ||
|
||
import ( | ||
"fmt" | ||
|
||
"github.com/brunomvsouza/singleflight" | ||
) | ||
|
||
func main() { | ||
var group singleflight.Group[string, string] | ||
|
||
semaphore := make(chan struct{}) | ||
|
||
res1c := group.DoChan("key", func() (string, error) { | ||
fmt.Printf("func 1 begin\n") | ||
defer fmt.Printf("func 1 end\n") | ||
<-semaphore | ||
return "func 1", nil | ||
}) | ||
|
||
res2c := group.DoChan("key", func() (string, error) { | ||
fmt.Printf("func 2 begin\n") | ||
defer fmt.Printf("func 2 end\n") | ||
<-semaphore | ||
return "func 2", nil | ||
}) | ||
|
||
close(semaphore) | ||
|
||
res1 := <-res1c | ||
res2 := <-res2c | ||
|
||
// Results are shared by functions executed with | ||
// duplicate keys. | ||
fmt.Println("Shared:", res2.Shared) | ||
// Only the first function is executed: it is registered and | ||
// started with "key", and doesn't complete before the second | ||
// funtion is registered with a duplicate key. | ||
fmt.Println("Equal results:", res1.Val == res2.Val) | ||
fmt.Println("Result:", res1.Val) | ||
|
||
// Output: | ||
// Shared: true | ||
// Equal results: true | ||
// Result: func 1 | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
// Copyright (c) 2023 Bruno Marques Venceslau de Souza. All rights reserved. | ||
// Use of this source code is governed by a BSD-style | ||
// license that can be found in the LICENSE file. | ||
|
||
package main | ||
|
||
import ( | ||
"fmt" | ||
"sync" | ||
"time" | ||
|
||
"github.com/brunomvsouza/singleflight" | ||
) | ||
|
||
func main() { | ||
var ( | ||
group singleflight.Group[string, string] | ||
wg sync.WaitGroup | ||
) | ||
|
||
wg.Add(4) | ||
|
||
go func() { | ||
defer wg.Done() | ||
res1, err1, shared1 := group.Do("key", func() (string, error) { | ||
time.Sleep(1 * time.Second) | ||
return "func 1", nil | ||
}) | ||
fmt.Println("res1:", res1) | ||
fmt.Println("err1:", err1) | ||
fmt.Println("shared1:", shared1) | ||
}() | ||
|
||
go func() { | ||
defer wg.Done() | ||
res2, err2, shared2 := group.Do("key", func() (string, error) { | ||
time.Sleep(1 * time.Second) | ||
return "func 2", nil | ||
}) | ||
fmt.Println("res2:", res2) | ||
fmt.Println("err2:", err2) | ||
fmt.Println("shared2:", shared2) | ||
}() | ||
|
||
go func() { | ||
defer wg.Done() | ||
time.Sleep(100 * time.Millisecond) | ||
group.Forget("key") | ||
}() | ||
|
||
go func() { | ||
defer wg.Done() | ||
time.Sleep(200 * time.Millisecond) | ||
res3, err3, shared3 := group.Do("key", func() (string, error) { | ||
time.Sleep(1 * time.Second) | ||
return "func 3", nil | ||
}) | ||
fmt.Println("res3:", res3) | ||
fmt.Println("err3:", err3) | ||
fmt.Println("shared3:", shared3) | ||
}() | ||
|
||
wg.Wait() | ||
|
||
// Output: | ||
// res2: func 1 | ||
// err2: <nil> | ||
// shared2: true | ||
// res1: func 1 | ||
// err1: <nil> | ||
// shared1: true | ||
// res3: func 3 | ||
// err3: <nil> | ||
// shared3: false | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.