fn/ContextGuard: use context.AfterFunc to wait
Simplifies context cancellation handling by using context.AfterFunc instead of a goroutine to wait for context cancellation. This approach avoids the overhead of a goroutine during the waiting period. For ctxQuitUnsafe, since g.quit is closed only in the Quit method (which also cancels all associated contexts), waiting on context cancellation ensures the same behavior without unnecessary dependency on g.quit. Added a test to ensure that the Create method does not launch any goroutines.
This commit is contained in:
2 files changed
+53
-20
No files matched your search
@@ -2,8 +2,11 @@ package fn
|
||||
|
||||
import (
|
||||
"context"
|
||||
"runtime"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
// TestContextGuard tests the behaviour of the ContextGuard.
|
||||
@@ -439,3 +442,36 @@ func TestContextGuard(t *testing.T) {
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// TestContextGuardCountGoroutines makes sure that ContextGuard doesn't create
|
||||
// any goroutines while waiting for contexts.
|
||||
func TestContextGuardCountGoroutines(t *testing.T) {
|
||||
// NOTE: t.Parallel() is not called in this test because it relies on an
|
||||
// accurate count of active goroutines. Running other tests in parallel
|
||||
// would introduce additional goroutines, leading to unreliable results.
|
||||
|
||||
g := NewContextGuard()
|
||||
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
|
||||
// Count goroutines before contexts are created.
|
||||
count1 := runtime.NumGoroutine()
|
||||
|
||||
// Create 1000 contexts of each type.
|
||||
for i := 0; i < 1000; i++ {
|
||||
_, _ = g.Create(ctx)
|
||||
_, _ = g.Create(ctx, WithBlockingCG())
|
||||
_, _ = g.Create(ctx, WithTimeoutCG())
|
||||
_, _ = g.Create(ctx, WithBlockingCG(), WithTimeoutCG())
|
||||
}
|
||||
|
||||
// Make sure no new goroutine was launched.
|
||||
count2 := runtime.NumGoroutine()
|
||||
require.LessOrEqual(t, count2, count1)
|
||||
|
||||
// Cancel root context.
|
||||
cancel()
|
||||
|
||||
// Make sure wg's counter gets to 0 eventually.
|
||||
g.WgWait()
|
||||
}
|
||||
Reference in new issue
Block a user