aboutsummaryrefslogtreecommitdiff
path: root/libgo/go/context
diff options
context:
space:
mode:
Diffstat (limited to 'libgo/go/context')
-rw-r--r--libgo/go/context/benchmark_test.go56
-rw-r--r--libgo/go/context/context.go14
-rw-r--r--libgo/go/context/example_test.go2
3 files changed, 63 insertions, 9 deletions
diff --git a/libgo/go/context/benchmark_test.go b/libgo/go/context/benchmark_test.go
index b792327..3c526dd 100644
--- a/libgo/go/context/benchmark_test.go
+++ b/libgo/go/context/benchmark_test.go
@@ -7,10 +7,64 @@ package context_test
import (
. "context"
"fmt"
+ "runtime"
+ "sync"
"testing"
+ "time"
)
-func BenchmarkContextCancelTree(b *testing.B) {
+func BenchmarkWithTimeout(b *testing.B) {
+ for concurrency := 40; concurrency <= 4e5; concurrency *= 100 {
+ name := fmt.Sprintf("concurrency=%d", concurrency)
+ b.Run(name, func(b *testing.B) {
+ benchmarkWithTimeout(b, concurrency)
+ })
+ }
+}
+
+func benchmarkWithTimeout(b *testing.B, concurrentContexts int) {
+ gomaxprocs := runtime.GOMAXPROCS(0)
+ perPContexts := concurrentContexts / gomaxprocs
+ root := Background()
+
+ // Generate concurrent contexts.
+ var wg sync.WaitGroup
+ ccf := make([][]CancelFunc, gomaxprocs)
+ for i := range ccf {
+ wg.Add(1)
+ go func(i int) {
+ defer wg.Done()
+ cf := make([]CancelFunc, perPContexts)
+ for j := range cf {
+ _, cf[j] = WithTimeout(root, time.Hour)
+ }
+ ccf[i] = cf
+ }(i)
+ }
+ wg.Wait()
+
+ b.ResetTimer()
+ b.RunParallel(func(pb *testing.PB) {
+ wcf := make([]CancelFunc, 10)
+ for pb.Next() {
+ for i := range wcf {
+ _, wcf[i] = WithTimeout(root, time.Hour)
+ }
+ for _, f := range wcf {
+ f()
+ }
+ }
+ })
+ b.StopTimer()
+
+ for _, cf := range ccf {
+ for _, f := range cf {
+ f()
+ }
+ }
+}
+
+func BenchmarkCancelTree(b *testing.B) {
depths := []int{1, 10, 100, 1000}
for _, d := range depths {
b.Run(fmt.Sprintf("depth=%d", d), func(b *testing.B) {
diff --git a/libgo/go/context/context.go b/libgo/go/context/context.go
index 892ff27..06580e0 100644
--- a/libgo/go/context/context.go
+++ b/libgo/go/context/context.go
@@ -136,7 +136,7 @@ type Context interface {
// // userKey is the key for user.User values in Contexts. It is
// // unexported; clients use user.NewContext and user.FromContext
// // instead of using this key directly.
- // var userKey key = 0
+ // var userKey key
//
// // NewContext returns a new Context that carries value u.
// func NewContext(ctx context.Context, u *User) context.Context {
@@ -380,25 +380,25 @@ func (c *cancelCtx) cancel(removeFromParent bool, err error) {
//
// Canceling this context releases resources associated with it, so code should
// call cancel as soon as the operations running in this Context complete.
-func WithDeadline(parent Context, deadline time.Time) (Context, CancelFunc) {
- if cur, ok := parent.Deadline(); ok && cur.Before(deadline) {
+func WithDeadline(parent Context, d time.Time) (Context, CancelFunc) {
+ if cur, ok := parent.Deadline(); ok && cur.Before(d) {
// The current deadline is already sooner than the new one.
return WithCancel(parent)
}
c := &timerCtx{
cancelCtx: newCancelCtx(parent),
- deadline: deadline,
+ deadline: d,
}
propagateCancel(parent, c)
- d := time.Until(deadline)
- if d <= 0 {
+ dur := time.Until(d)
+ if dur <= 0 {
c.cancel(true, DeadlineExceeded) // deadline has already passed
return c, func() { c.cancel(true, Canceled) }
}
c.mu.Lock()
defer c.mu.Unlock()
if c.err == nil {
- c.timer = time.AfterFunc(d, func() {
+ c.timer = time.AfterFunc(dur, func() {
c.cancel(true, DeadlineExceeded)
})
}
diff --git a/libgo/go/context/example_test.go b/libgo/go/context/example_test.go
index 2d48d4e..b2c2aa9 100644
--- a/libgo/go/context/example_test.go
+++ b/libgo/go/context/example_test.go
@@ -52,7 +52,7 @@ func ExampleWithCancel() {
// 5
}
-// This example passes a context with a arbitrary deadline to tell a blocking
+// This example passes a context with an arbitrary deadline to tell a blocking
// function that it should abandon its work as soon as it gets to it.
func ExampleWithDeadline() {
d := time.Now().Add(50 * time.Millisecond)