64
//
65
// Done is provided for use in select statements:
66
//
67
- // // DoSomething calls DoSomethingSlow and returns as soon as
68
- // // it returns or ctx.Done is closed.
69
- // func DoSomething(ctx context.Context) (Result, error) {
70
- // c := make(chan Result, 1)
71
- // go func() { c <- DoSomethingSlow(ctx) }()
72
- // select {
73
- // case res := <-c:
74
- // return res, nil
75
- // case <-ctx.Done():
76
- // return nil, ctx.Err()
77
- // }
78
- // }
67
+ // // Stream generates values with DoSomething and sends them to out
68
+ // // until DoSomething returns an error or ctx.Done is closed.
69
+ // func Stream(ctx context.Context, out <-chan Value) error {
70
+ // for {
71
+ // v, err := DoSomething(ctx)
72
+ // if err != nil {
73
+ // return err
74
+ // }
75
+ // select {
76
+ // case <-ctx.Done():
77
+ // return ctx.Err()
78
+ // case out <- v:
79
+ // }
80
+ // }
81
+ // }
82
//
83
// See http://blog.golang.org/pipelines for more examples of how to use
84
// a Done channel for cancelation.
111
// // Package user defines a User type that's stored in Contexts.
112
// package user
113
//
111
- // import "code.google.com/p/go.net/context"
114
+ // import "golang.org/x/net/context"
115
//
116
// // User is the type of value stored in the Contexts.
117
// type User struct {...}
127
//
128
// // NewContext returns a new Context that carries value u.
129
// func NewContext(ctx context.Context, u *User) context.Context {
127
- // return context.WithValue(userKey, u)
130
+ // return context.WithValue(ctx, userKey, u)
131
// }
132
//
133
// // FromContext returns the User value stored in ctx, if any.
145
// deadline passes.
146
var DeadlineExceeded = errors.New("context deadline exceeded")
147
145
-// An emptyCtx is never canceled, has no values, and has no deadline.
148
+// An emptyCtx is never canceled, has no values, and has no deadline. It is not
149
+// struct{}, since vars of this type must have distinct addresses.
150
type emptyCtx int
151
148
-func (emptyCtx) Deadline() (deadline time.Time, ok bool) {
152
+func (*emptyCtx) Deadline() (deadline time.Time, ok bool) {
153
return
154
}
155
152
-func (emptyCtx) Done() <-chan struct{} {
156
+func (*emptyCtx) Done() <-chan struct{} {
157
return nil
158
}
159
156
-func (emptyCtx) Err() error {
160
+func (*emptyCtx) Err() error {
161
return nil
162
}
163
160
-func (emptyCtx) Value(key interface{}) interface{} {
164
+func (*emptyCtx) Value(key interface{}) interface{} {
165
return nil
166
}
167
164
-func (n emptyCtx) String() string {
165
- switch n {
168
+func (e *emptyCtx) String() string {
169
+ switch e {
170
case background:
171
return "context.Background"
172
case todo:
175
return "unknown empty Context"
176
}
177
174
-const (
175
- background emptyCtx = 1
176
- todo emptyCtx = 2
178
+var (
179
+ background = new(emptyCtx)
180
+ todo = new(emptyCtx)
181
)
182
183
// Background returns a non-nil, empty Context. It is never canceled, has no
205
// WithCancel returns a copy of parent with a new Done channel. The returned
206
// context's Done channel is closed when the returned cancel function is called
207
// or when the parent context's Done channel is closed, whichever happens first.
208
+//
209
+// Canceling this context releases resources associated with it, so code should
210
+// call cancel as soon as the operations running in this Context complete.
211
func WithCancel(parent Context) (ctx Context, cancel CancelFunc) {
212
c := newCancelCtx(parent)
213
propagateCancel(parent, &c)
268
}
269
}
270
271
+// removeChild removes a context from its parent.
272
+func removeChild(parent Context, child canceler) {
273
+ p, ok := parentCancelCtx(parent)
274
+ if !ok {
275
+ return
276
+ }
277
+ p.mu.Lock()
278
+ if p.children != nil {
279
+ delete(p.children, child)
280
+ }
281
+ p.mu.Unlock()
282
+}
283
+
284
// A canceler is a context type that can be canceled directly. The
285
// implementations are *cancelCtx and *timerCtx.
286
type canceler interface {
335
c.mu.Unlock()
336
337
if removeFromParent {
318
- if p, ok := parentCancelCtx(c.Context); ok {
319
- p.mu.Lock()
320
- if p.children != nil {
321
- delete(p.children, c)
322
- }
323
- p.mu.Unlock()
324
- }
338
+ removeChild(c.Context, c)
339
}
340
}
341
346
// cancel function is called, or when the parent context's Done channel is
347
// closed, whichever happens first.
348
//
335
-// Canceling this context releases resources associated with the deadline
336
-// timer, so code should call cancel as soon as the operations running in this
337
-// Context complete.
349
+// Canceling this context releases resources associated with it, so code should
350
+// call cancel as soon as the operations running in this Context complete.
351
func WithDeadline(parent Context, deadline time.Time) (Context, CancelFunc) {
352
if cur, ok := parent.Deadline(); ok && cur.Before(deadline) {
353
// The current deadline is already sooner than the new one.
392
}
393
394
func (c *timerCtx) cancel(removeFromParent bool, err error) {
382
- c.cancelCtx.cancel(removeFromParent, err)
395
+ c.cancelCtx.cancel(false, err)
396
+ if removeFromParent {
397
+ // Remove this timerCtx from its parent cancelCtx's children.
398
+ removeChild(c.cancelCtx.Context, c)
399
+ }
400
c.mu.Lock()
401
if c.timer != nil {
402
c.timer.Stop()
407
408
// WithTimeout returns WithDeadline(parent, time.Now().Add(timeout)).
409
//
393
-// Canceling this context releases resources associated with the deadline
394
-// timer, so code should call cancel as soon as the operations running in this
395
-// Context complete:
410
+// Canceling this context releases resources associated with it, so code should
411
+// call cancel as soon as the operations running in this Context complete:
412
//
413
// func slowOperationWithTimeout(ctx context.Context) (Result, error) {
414
// ctx, cancel := context.WithTimeout(ctx, 100*time.Millisecond)