syncs: delete WaitGroup and use sync.WaitGroup.Go in Go 1.25

Our own WaitGroup wrapper type was a prototype implementation
for the Go method on the standard sync.WaitGroup type.
Now that there is first-class support for Go,
we should migrate over to using it and delete syncs.WaitGroup.

Updates #cleanup
Updates tailscale/tailscale#16330

Change-Id: Ib52b10f9847341ce29b4ca0da927dc9321691235
Signed-off-by: Joe Tsai <joetsai@digital-static.net>
This commit is contained in:
Joe Tsai 2025-08-28 14:09:01 -07:00 committed by Brad Fitzpatrick
parent f5d3c59a92
commit 3aea0e095a
6 changed files with 9 additions and 26 deletions

View File

@ -18,6 +18,7 @@ import (
"reflect" "reflect"
"strconv" "strconv"
"strings" "strings"
"sync"
"time" "time"
"github.com/fsnotify/fsnotify" "github.com/fsnotify/fsnotify"
@ -26,7 +27,6 @@ import (
"tailscale.com/kube/egressservices" "tailscale.com/kube/egressservices"
"tailscale.com/kube/kubeclient" "tailscale.com/kube/kubeclient"
"tailscale.com/kube/kubetypes" "tailscale.com/kube/kubetypes"
"tailscale.com/syncs"
"tailscale.com/tailcfg" "tailscale.com/tailcfg"
"tailscale.com/util/httpm" "tailscale.com/util/httpm"
"tailscale.com/util/linuxfw" "tailscale.com/util/linuxfw"
@ -666,8 +666,7 @@ func (ep *egressProxy) waitTillSafeToShutdown(ctx context.Context, cfgs *egresss
return return
} }
log.Printf("Ensuring that cluster traffic for egress targets is no longer routed via this Pod...") log.Printf("Ensuring that cluster traffic for egress targets is no longer routed via this Pod...")
wg := syncs.WaitGroup{} var wg sync.WaitGroup
for s, cfg := range *cfgs { for s, cfg := range *cfgs {
hep := cfg.HealthCheckEndpoint hep := cfg.HealthCheckEndpoint
if hep == "" { if hep == "" {

View File

@ -20,6 +20,7 @@ import (
"path" "path"
"path/filepath" "path/filepath"
"strings" "strings"
"sync"
"sync/atomic" "sync/atomic"
"time" "time"
"unicode/utf8" "unicode/utf8"
@ -32,7 +33,6 @@ import (
"tailscale.com/envknob" "tailscale.com/envknob"
"tailscale.com/ipn/ipnstate" "tailscale.com/ipn/ipnstate"
"tailscale.com/net/tsaddr" "tailscale.com/net/tsaddr"
"tailscale.com/syncs"
"tailscale.com/tailcfg" "tailscale.com/tailcfg"
tsrate "tailscale.com/tstime/rate" tsrate "tailscale.com/tstime/rate"
"tailscale.com/util/quarantine" "tailscale.com/util/quarantine"
@ -176,7 +176,7 @@ func runCp(ctx context.Context, args []string) error {
log.Printf("sending %q to %v/%v/%v ...", name, target, ip, stableID) log.Printf("sending %q to %v/%v/%v ...", name, target, ip, stableID)
} }
var group syncs.WaitGroup var group sync.WaitGroup
ctxProgress, cancelProgress := context.WithCancel(ctx) ctxProgress, cancelProgress := context.WithCancel(ctx)
defer cancelProgress() defer cancelProgress()
if isatty.IsTerminal(os.Stderr.Fd()) { if isatty.IsTerminal(os.Stderr.Fd()) {

View File

@ -140,7 +140,7 @@ tailscale.com/cmd/tailscale dependencies: (generated by github.com/tailscale/dep
💣 tailscale.com/net/tshttpproxy from tailscale.com/clientupdate/distsign+ 💣 tailscale.com/net/tshttpproxy from tailscale.com/clientupdate/distsign+
tailscale.com/paths from tailscale.com/client/local+ tailscale.com/paths from tailscale.com/client/local+
💣 tailscale.com/safesocket from tailscale.com/client/local+ 💣 tailscale.com/safesocket from tailscale.com/client/local+
tailscale.com/syncs from tailscale.com/cmd/tailscale/cli+ tailscale.com/syncs from tailscale.com/control/controlhttp+
tailscale.com/tailcfg from tailscale.com/client/local+ tailscale.com/tailcfg from tailscale.com/client/local+
tailscale.com/tempfork/spf13/cobra from tailscale.com/cmd/tailscale/cli/ffcomplete+ tailscale.com/tempfork/spf13/cobra from tailscale.com/cmd/tailscale/cli/ffcomplete+
tailscale.com/tka from tailscale.com/client/local+ tailscale.com/tka from tailscale.com/client/local+

View File

@ -12,7 +12,6 @@ import (
"time" "time"
"tailscale.com/ipn" "tailscale.com/ipn"
"tailscale.com/syncs"
"tailscale.com/tstime" "tailscale.com/tstime"
"tailscale.com/types/logger" "tailscale.com/types/logger"
) )
@ -33,7 +32,7 @@ type fileDeleter struct {
byName map[string]*list.Element byName map[string]*list.Element
emptySignal chan struct{} // signal that the queue is empty emptySignal chan struct{} // signal that the queue is empty
group syncs.WaitGroup group sync.WaitGroup
shutdownCtx context.Context shutdownCtx context.Context
shutdown context.CancelFunc shutdown context.CancelFunc
fs FileOps // must be used for all filesystem operations fs FileOps // must be used for all filesystem operations

View File

@ -402,19 +402,3 @@ func (m *Map[K, V]) Swap(key K, value V) (oldValue V) {
mak.Set(&m.m, key, value) mak.Set(&m.m, key, value)
return oldValue return oldValue
} }
// WaitGroup is identical to [sync.WaitGroup],
// but provides a Go method to start a goroutine.
type WaitGroup struct{ sync.WaitGroup }
// Go calls the given function in a new goroutine.
// It automatically increments the counter before execution and
// automatically decrements the counter after execution.
// It must not be called concurrently with Wait.
func (wg *WaitGroup) Go(f func()) {
wg.Add(1)
go func() {
defer wg.Done()
f()
}()
}

View File

@ -7,6 +7,7 @@ import (
"context" "context"
"io" "io"
"os" "os"
"sync"
"testing" "testing"
"time" "time"
@ -98,7 +99,7 @@ func TestMutexValue(t *testing.T) {
t.Errorf("Load = %v, want %v", v.Load(), now) t.Errorf("Load = %v, want %v", v.Load(), now)
} }
var group WaitGroup var group sync.WaitGroup
var v2 MutexValue[int] var v2 MutexValue[int]
var sum int var sum int
for i := range 10 { for i := range 10 {
@ -237,7 +238,7 @@ func TestMap(t *testing.T) {
t.Run("LoadOrStore", func(t *testing.T) { t.Run("LoadOrStore", func(t *testing.T) {
var m Map[string, string] var m Map[string, string]
var wg WaitGroup var wg sync.WaitGroup
var ok1, ok2 bool var ok1, ok2 bool
wg.Go(func() { _, ok1 = m.LoadOrStore("", "") }) wg.Go(func() { _, ok1 = m.LoadOrStore("", "") })
wg.Go(func() { _, ok2 = m.LoadOrStore("", "") }) wg.Go(func() { _, ok2 = m.LoadOrStore("", "") })