From 9ea9e62ee8459785e5be6c6a2c00ac3dd15e0355 Mon Sep 17 00:00:00 2001 From: yusing Date: Wed, 7 Jan 2026 17:17:12 +0800 Subject: [PATCH] refactor: remove NoCopy struct; move RefCounter struct to goutils and update usage; remove internal/utils entirely --- goutils | 2 +- internal/idlewatcher/watcher.go | 2 - internal/logging/accesslog/file_logger.go | 6 +- internal/net/gphttp/loadbalancer/server.go | 3 - internal/route/route.go | 3 - internal/utils/nocopy.go | 8 --- internal/utils/ref_count.go | 54 --------------- internal/utils/ref_count_test.go | 78 ---------------------- 8 files changed, 4 insertions(+), 152 deletions(-) delete mode 100644 internal/utils/nocopy.go delete mode 100644 internal/utils/ref_count.go delete mode 100644 internal/utils/ref_count_test.go diff --git a/goutils b/goutils index 06f20f6b..4b046d27 160000 --- a/goutils +++ b/goutils @@ -1 +1 @@ -Subproject commit 06f20f6b8710dabab8287b128d109d065da3b281 +Subproject commit 4b046d275fbfc49de3c02038983b775a95a3a8f6 diff --git a/internal/idlewatcher/watcher.go b/internal/idlewatcher/watcher.go index c2c28845..de19e3fe 100644 --- a/internal/idlewatcher/watcher.go +++ b/internal/idlewatcher/watcher.go @@ -19,7 +19,6 @@ import ( nettypes "github.com/yusing/godoxy/internal/net/types" "github.com/yusing/godoxy/internal/route/routes" "github.com/yusing/godoxy/internal/types" - U "github.com/yusing/godoxy/internal/utils" "github.com/yusing/godoxy/internal/watcher/events" "github.com/yusing/godoxy/internal/watcher/health/monitor" gperr "github.com/yusing/goutils/errs" @@ -48,7 +47,6 @@ type ( } Watcher struct { - _ U.NoCopy routeHelper l zerolog.Logger diff --git a/internal/logging/accesslog/file_logger.go b/internal/logging/accesslog/file_logger.go index 168ceb36..a845fb7c 100644 --- a/internal/logging/accesslog/file_logger.go +++ b/internal/logging/accesslog/file_logger.go @@ -8,7 +8,7 @@ import ( "sync" "github.com/rs/zerolog/log" - "github.com/yusing/godoxy/internal/utils" + "github.com/yusing/goutils/synk" ) type File struct { @@ -18,7 +18,7 @@ type File struct { // Store it for later delete from `openedFiles`. path string - refCount *utils.RefCount + refCount *synk.RefCount } var ( @@ -55,7 +55,7 @@ func NewFileIO(path string) (Writer, error) { if _, err := f.Seek(0, io.SeekEnd); err != nil { return nil, fmt.Errorf("access log seek error: %w", err) } - file = &File{f: f, path: path, refCount: utils.NewRefCounter()} + file = &File{f: f, path: path, refCount: synk.NewRefCounter()} openedFiles[path] = file go file.closeOnZero() return file, nil diff --git a/internal/net/gphttp/loadbalancer/server.go b/internal/net/gphttp/loadbalancer/server.go index b94aba09..26e4b800 100644 --- a/internal/net/gphttp/loadbalancer/server.go +++ b/internal/net/gphttp/loadbalancer/server.go @@ -7,12 +7,9 @@ import ( idlewatcher "github.com/yusing/godoxy/internal/idlewatcher/types" nettypes "github.com/yusing/godoxy/internal/net/types" "github.com/yusing/godoxy/internal/types" - U "github.com/yusing/godoxy/internal/utils" ) type server struct { - _ U.NoCopy - name string url *nettypes.URL weight int diff --git a/internal/route/route.go b/internal/route/route.go index f1f162db..99de1237 100644 --- a/internal/route/route.go +++ b/internal/route/route.go @@ -36,13 +36,10 @@ import ( "github.com/yusing/godoxy/internal/route/rules" rulepresets "github.com/yusing/godoxy/internal/route/rules/presets" route "github.com/yusing/godoxy/internal/route/types" - "github.com/yusing/godoxy/internal/utils" ) type ( Route struct { - _ utils.NoCopy - Alias string `json:"alias"` Scheme route.Scheme `json:"scheme,omitempty" swaggertype:"string" enums:"http,https,h2c,tcp,udp,fileserver"` Host string `json:"host,omitempty"` diff --git a/internal/utils/nocopy.go b/internal/utils/nocopy.go deleted file mode 100644 index f3443745..00000000 --- a/internal/utils/nocopy.go +++ /dev/null @@ -1,8 +0,0 @@ -package utils - -// empty struct that implements Locker interface -// for hinting that no copy should be performed. -type NoCopy struct{} - -func (*NoCopy) Lock() {} -func (*NoCopy) Unlock() {} diff --git a/internal/utils/ref_count.go b/internal/utils/ref_count.go deleted file mode 100644 index 782783ac..00000000 --- a/internal/utils/ref_count.go +++ /dev/null @@ -1,54 +0,0 @@ -package utils - -import ( - "sync/atomic" -) - -type RefCount struct { - _ NoCopy - - refCount uint32 - zeroCh chan struct{} -} - -func NewRefCounter() *RefCount { - rc := &RefCount{ - refCount: 1, - zeroCh: make(chan struct{}), - } - return rc -} - -func (rc *RefCount) Zero() <-chan struct{} { - return rc.zeroCh -} - -func (rc *RefCount) Add() { - // We add before checking to ensure proper ordering - newV := atomic.AddUint32(&rc.refCount, 1) - if newV == 1 { - // If it was 0 before we added, that means we're incrementing after a close - // This is a programming error - panic("RefCount.Add() called after count reached zero") - } -} - -func (rc *RefCount) Sub() { - // First read the current value - for { - current := atomic.LoadUint32(&rc.refCount) - if current == 0 { - // Already at zero, channel should be closed - return - } - - // Try to decrement, but only if the value hasn't changed - if atomic.CompareAndSwapUint32(&rc.refCount, current, current-1) { - if current == 1 { // Was this the last reference? - close(rc.zeroCh) - } - return - } - // If CAS failed, someone else modified the count, try again - } -} diff --git a/internal/utils/ref_count_test.go b/internal/utils/ref_count_test.go deleted file mode 100644 index a40cc75b..00000000 --- a/internal/utils/ref_count_test.go +++ /dev/null @@ -1,78 +0,0 @@ -package utils - -import ( - "sync" - "testing" - "time" - - expect "github.com/yusing/goutils/testing" -) - -func TestRefCounterAddSub(t *testing.T) { - rc := NewRefCounter() // Count starts at 1 - - var wg sync.WaitGroup - - rc.Add() - for range 2 { - wg.Go(rc.Sub) - } - - wg.Wait() - expect.Equal(t, int(rc.refCount), 0) - - select { - case <-rc.Zero(): - // Expected behavior - case <-time.After(1 * time.Second): - t.Fatal("Expected Zero channel to close, but it didn't") - } -} - -func TestRefCounterMultipleAddSub(t *testing.T) { - rc := NewRefCounter() - - var wg sync.WaitGroup - numAdds := 5 - numSubs := 5 - wg.Add(numAdds) - - for range numAdds { - go func() { - defer wg.Done() - rc.Add() - }() - } - wg.Wait() - expect.Equal(t, int(rc.refCount), numAdds+1) - - wg.Add(numSubs) - for range numSubs { - go func() { - defer wg.Done() - rc.Sub() - }() - } - wg.Wait() - expect.Equal(t, int(rc.refCount), numAdds+1-numSubs) - - rc.Sub() - select { - case <-rc.Zero(): - // Expected behavior - case <-time.After(1 * time.Second): - t.Fatal("Expected Zero channel to close, but it didn't") - } -} - -func TestRefCounterOneInitially(t *testing.T) { - rc := NewRefCounter() - rc.Sub() // Bring count to zero - - select { - case <-rc.Zero(): - // Expected behavior - case <-time.After(1 * time.Second): - t.Fatal("Expected Zero channel to close, but it didn't") - } -}