ducky/devices

Paddy 2015-11-12

0:b6494e1a499e Go to Latest

ducky/devices/vendor/golang.org/x/net/context/context.go

Initial attempt. Create the basic types (Device, DeviceType, DeviceChange) that we'll be using in the service. Also, create our Storer interface, and the helper methods to store, retrieve, and update information in the datastore. Also, we're using Godep, so check in our Godeps folder and the vendor folder. Note that this only works on Go 1.5 and later, with the GO15VENDOREXPERIMENT environment variable set to 1.

History
paddy@0 1 // Copyright 2014 The Go Authors. All rights reserved.
paddy@0 2 // Use of this source code is governed by a BSD-style
paddy@0 3 // license that can be found in the LICENSE file.
paddy@0 4
paddy@0 5 // Package context defines the Context type, which carries deadlines,
paddy@0 6 // cancelation signals, and other request-scoped values across API boundaries
paddy@0 7 // and between processes.
paddy@0 8 //
paddy@0 9 // Incoming requests to a server should create a Context, and outgoing calls to
paddy@0 10 // servers should accept a Context. The chain of function calls between must
paddy@0 11 // propagate the Context, optionally replacing it with a modified copy created
paddy@0 12 // using WithDeadline, WithTimeout, WithCancel, or WithValue.
paddy@0 13 //
paddy@0 14 // Programs that use Contexts should follow these rules to keep interfaces
paddy@0 15 // consistent across packages and enable static analysis tools to check context
paddy@0 16 // propagation:
paddy@0 17 //
paddy@0 18 // Do not store Contexts inside a struct type; instead, pass a Context
paddy@0 19 // explicitly to each function that needs it. The Context should be the first
paddy@0 20 // parameter, typically named ctx:
paddy@0 21 //
paddy@0 22 // func DoSomething(ctx context.Context, arg Arg) error {
paddy@0 23 // // ... use ctx ...
paddy@0 24 // }
paddy@0 25 //
paddy@0 26 // Do not pass a nil Context, even if a function permits it. Pass context.TODO
paddy@0 27 // if you are unsure about which Context to use.
paddy@0 28 //
paddy@0 29 // Use context Values only for request-scoped data that transits processes and
paddy@0 30 // APIs, not for passing optional parameters to functions.
paddy@0 31 //
paddy@0 32 // The same Context may be passed to functions running in different goroutines;
paddy@0 33 // Contexts are safe for simultaneous use by multiple goroutines.
paddy@0 34 //
paddy@0 35 // See http://blog.golang.org/context for example code for a server that uses
paddy@0 36 // Contexts.
paddy@0 37 package context
paddy@0 38
paddy@0 39 import (
paddy@0 40 "errors"
paddy@0 41 "fmt"
paddy@0 42 "sync"
paddy@0 43 "time"
paddy@0 44 )
paddy@0 45
paddy@0 46 // A Context carries a deadline, a cancelation signal, and other values across
paddy@0 47 // API boundaries.
paddy@0 48 //
paddy@0 49 // Context's methods may be called by multiple goroutines simultaneously.
paddy@0 50 type Context interface {
paddy@0 51 // Deadline returns the time when work done on behalf of this context
paddy@0 52 // should be canceled. Deadline returns ok==false when no deadline is
paddy@0 53 // set. Successive calls to Deadline return the same results.
paddy@0 54 Deadline() (deadline time.Time, ok bool)
paddy@0 55
paddy@0 56 // Done returns a channel that's closed when work done on behalf of this
paddy@0 57 // context should be canceled. Done may return nil if this context can
paddy@0 58 // never be canceled. Successive calls to Done return the same value.
paddy@0 59 //
paddy@0 60 // WithCancel arranges for Done to be closed when cancel is called;
paddy@0 61 // WithDeadline arranges for Done to be closed when the deadline
paddy@0 62 // expires; WithTimeout arranges for Done to be closed when the timeout
paddy@0 63 // elapses.
paddy@0 64 //
paddy@0 65 // Done is provided for use in select statements:
paddy@0 66 //
paddy@0 67 // // Stream generates values with DoSomething and sends them to out
paddy@0 68 // // until DoSomething returns an error or ctx.Done is closed.
paddy@0 69 // func Stream(ctx context.Context, out <-chan Value) error {
paddy@0 70 // for {
paddy@0 71 // v, err := DoSomething(ctx)
paddy@0 72 // if err != nil {
paddy@0 73 // return err
paddy@0 74 // }
paddy@0 75 // select {
paddy@0 76 // case <-ctx.Done():
paddy@0 77 // return ctx.Err()
paddy@0 78 // case out <- v:
paddy@0 79 // }
paddy@0 80 // }
paddy@0 81 // }
paddy@0 82 //
paddy@0 83 // See http://blog.golang.org/pipelines for more examples of how to use
paddy@0 84 // a Done channel for cancelation.
paddy@0 85 Done() <-chan struct{}
paddy@0 86
paddy@0 87 // Err returns a non-nil error value after Done is closed. Err returns
paddy@0 88 // Canceled if the context was canceled or DeadlineExceeded if the
paddy@0 89 // context's deadline passed. No other values for Err are defined.
paddy@0 90 // After Done is closed, successive calls to Err return the same value.
paddy@0 91 Err() error
paddy@0 92
paddy@0 93 // Value returns the value associated with this context for key, or nil
paddy@0 94 // if no value is associated with key. Successive calls to Value with
paddy@0 95 // the same key returns the same result.
paddy@0 96 //
paddy@0 97 // Use context values only for request-scoped data that transits
paddy@0 98 // processes and API boundaries, not for passing optional parameters to
paddy@0 99 // functions.
paddy@0 100 //
paddy@0 101 // A key identifies a specific value in a Context. Functions that wish
paddy@0 102 // to store values in Context typically allocate a key in a global
paddy@0 103 // variable then use that key as the argument to context.WithValue and
paddy@0 104 // Context.Value. A key can be any type that supports equality;
paddy@0 105 // packages should define keys as an unexported type to avoid
paddy@0 106 // collisions.
paddy@0 107 //
paddy@0 108 // Packages that define a Context key should provide type-safe accessors
paddy@0 109 // for the values stores using that key:
paddy@0 110 //
paddy@0 111 // // Package user defines a User type that's stored in Contexts.
paddy@0 112 // package user
paddy@0 113 //
paddy@0 114 // import "golang.org/x/net/context"
paddy@0 115 //
paddy@0 116 // // User is the type of value stored in the Contexts.
paddy@0 117 // type User struct {...}
paddy@0 118 //
paddy@0 119 // // key is an unexported type for keys defined in this package.
paddy@0 120 // // This prevents collisions with keys defined in other packages.
paddy@0 121 // type key int
paddy@0 122 //
paddy@0 123 // // userKey is the key for user.User values in Contexts. It is
paddy@0 124 // // unexported; clients use user.NewContext and user.FromContext
paddy@0 125 // // instead of using this key directly.
paddy@0 126 // var userKey key = 0
paddy@0 127 //
paddy@0 128 // // NewContext returns a new Context that carries value u.
paddy@0 129 // func NewContext(ctx context.Context, u *User) context.Context {
paddy@0 130 // return context.WithValue(ctx, userKey, u)
paddy@0 131 // }
paddy@0 132 //
paddy@0 133 // // FromContext returns the User value stored in ctx, if any.
paddy@0 134 // func FromContext(ctx context.Context) (*User, bool) {
paddy@0 135 // u, ok := ctx.Value(userKey).(*User)
paddy@0 136 // return u, ok
paddy@0 137 // }
paddy@0 138 Value(key interface{}) interface{}
paddy@0 139 }
paddy@0 140
paddy@0 141 // Canceled is the error returned by Context.Err when the context is canceled.
paddy@0 142 var Canceled = errors.New("context canceled")
paddy@0 143
paddy@0 144 // DeadlineExceeded is the error returned by Context.Err when the context's
paddy@0 145 // deadline passes.
paddy@0 146 var DeadlineExceeded = errors.New("context deadline exceeded")
paddy@0 147
paddy@0 148 // An emptyCtx is never canceled, has no values, and has no deadline. It is not
paddy@0 149 // struct{}, since vars of this type must have distinct addresses.
paddy@0 150 type emptyCtx int
paddy@0 151
paddy@0 152 func (*emptyCtx) Deadline() (deadline time.Time, ok bool) {
paddy@0 153 return
paddy@0 154 }
paddy@0 155
paddy@0 156 func (*emptyCtx) Done() <-chan struct{} {
paddy@0 157 return nil
paddy@0 158 }
paddy@0 159
paddy@0 160 func (*emptyCtx) Err() error {
paddy@0 161 return nil
paddy@0 162 }
paddy@0 163
paddy@0 164 func (*emptyCtx) Value(key interface{}) interface{} {
paddy@0 165 return nil
paddy@0 166 }
paddy@0 167
paddy@0 168 func (e *emptyCtx) String() string {
paddy@0 169 switch e {
paddy@0 170 case background:
paddy@0 171 return "context.Background"
paddy@0 172 case todo:
paddy@0 173 return "context.TODO"
paddy@0 174 }
paddy@0 175 return "unknown empty Context"
paddy@0 176 }
paddy@0 177
paddy@0 178 var (
paddy@0 179 background = new(emptyCtx)
paddy@0 180 todo = new(emptyCtx)
paddy@0 181 )
paddy@0 182
paddy@0 183 // Background returns a non-nil, empty Context. It is never canceled, has no
paddy@0 184 // values, and has no deadline. It is typically used by the main function,
paddy@0 185 // initialization, and tests, and as the top-level Context for incoming
paddy@0 186 // requests.
paddy@0 187 func Background() Context {
paddy@0 188 return background
paddy@0 189 }
paddy@0 190
paddy@0 191 // TODO returns a non-nil, empty Context. Code should use context.TODO when
paddy@0 192 // it's unclear which Context to use or it's is not yet available (because the
paddy@0 193 // surrounding function has not yet been extended to accept a Context
paddy@0 194 // parameter). TODO is recognized by static analysis tools that determine
paddy@0 195 // whether Contexts are propagated correctly in a program.
paddy@0 196 func TODO() Context {
paddy@0 197 return todo
paddy@0 198 }
paddy@0 199
paddy@0 200 // A CancelFunc tells an operation to abandon its work.
paddy@0 201 // A CancelFunc does not wait for the work to stop.
paddy@0 202 // After the first call, subsequent calls to a CancelFunc do nothing.
paddy@0 203 type CancelFunc func()
paddy@0 204
paddy@0 205 // WithCancel returns a copy of parent with a new Done channel. The returned
paddy@0 206 // context's Done channel is closed when the returned cancel function is called
paddy@0 207 // or when the parent context's Done channel is closed, whichever happens first.
paddy@0 208 //
paddy@0 209 // Canceling this context releases resources associated with it, so code should
paddy@0 210 // call cancel as soon as the operations running in this Context complete.
paddy@0 211 func WithCancel(parent Context) (ctx Context, cancel CancelFunc) {
paddy@0 212 c := newCancelCtx(parent)
paddy@0 213 propagateCancel(parent, &c)
paddy@0 214 return &c, func() { c.cancel(true, Canceled) }
paddy@0 215 }
paddy@0 216
paddy@0 217 // newCancelCtx returns an initialized cancelCtx.
paddy@0 218 func newCancelCtx(parent Context) cancelCtx {
paddy@0 219 return cancelCtx{
paddy@0 220 Context: parent,
paddy@0 221 done: make(chan struct{}),
paddy@0 222 }
paddy@0 223 }
paddy@0 224
paddy@0 225 // propagateCancel arranges for child to be canceled when parent is.
paddy@0 226 func propagateCancel(parent Context, child canceler) {
paddy@0 227 if parent.Done() == nil {
paddy@0 228 return // parent is never canceled
paddy@0 229 }
paddy@0 230 if p, ok := parentCancelCtx(parent); ok {
paddy@0 231 p.mu.Lock()
paddy@0 232 if p.err != nil {
paddy@0 233 // parent has already been canceled
paddy@0 234 child.cancel(false, p.err)
paddy@0 235 } else {
paddy@0 236 if p.children == nil {
paddy@0 237 p.children = make(map[canceler]bool)
paddy@0 238 }
paddy@0 239 p.children[child] = true
paddy@0 240 }
paddy@0 241 p.mu.Unlock()
paddy@0 242 } else {
paddy@0 243 go func() {
paddy@0 244 select {
paddy@0 245 case <-parent.Done():
paddy@0 246 child.cancel(false, parent.Err())
paddy@0 247 case <-child.Done():
paddy@0 248 }
paddy@0 249 }()
paddy@0 250 }
paddy@0 251 }
paddy@0 252
paddy@0 253 // parentCancelCtx follows a chain of parent references until it finds a
paddy@0 254 // *cancelCtx. This function understands how each of the concrete types in this
paddy@0 255 // package represents its parent.
paddy@0 256 func parentCancelCtx(parent Context) (*cancelCtx, bool) {
paddy@0 257 for {
paddy@0 258 switch c := parent.(type) {
paddy@0 259 case *cancelCtx:
paddy@0 260 return c, true
paddy@0 261 case *timerCtx:
paddy@0 262 return &c.cancelCtx, true
paddy@0 263 case *valueCtx:
paddy@0 264 parent = c.Context
paddy@0 265 default:
paddy@0 266 return nil, false
paddy@0 267 }
paddy@0 268 }
paddy@0 269 }
paddy@0 270
paddy@0 271 // removeChild removes a context from its parent.
paddy@0 272 func removeChild(parent Context, child canceler) {
paddy@0 273 p, ok := parentCancelCtx(parent)
paddy@0 274 if !ok {
paddy@0 275 return
paddy@0 276 }
paddy@0 277 p.mu.Lock()
paddy@0 278 if p.children != nil {
paddy@0 279 delete(p.children, child)
paddy@0 280 }
paddy@0 281 p.mu.Unlock()
paddy@0 282 }
paddy@0 283
paddy@0 284 // A canceler is a context type that can be canceled directly. The
paddy@0 285 // implementations are *cancelCtx and *timerCtx.
paddy@0 286 type canceler interface {
paddy@0 287 cancel(removeFromParent bool, err error)
paddy@0 288 Done() <-chan struct{}
paddy@0 289 }
paddy@0 290
paddy@0 291 // A cancelCtx can be canceled. When canceled, it also cancels any children
paddy@0 292 // that implement canceler.
paddy@0 293 type cancelCtx struct {
paddy@0 294 Context
paddy@0 295
paddy@0 296 done chan struct{} // closed by the first cancel call.
paddy@0 297
paddy@0 298 mu sync.Mutex
paddy@0 299 children map[canceler]bool // set to nil by the first cancel call
paddy@0 300 err error // set to non-nil by the first cancel call
paddy@0 301 }
paddy@0 302
paddy@0 303 func (c *cancelCtx) Done() <-chan struct{} {
paddy@0 304 return c.done
paddy@0 305 }
paddy@0 306
paddy@0 307 func (c *cancelCtx) Err() error {
paddy@0 308 c.mu.Lock()
paddy@0 309 defer c.mu.Unlock()
paddy@0 310 return c.err
paddy@0 311 }
paddy@0 312
paddy@0 313 func (c *cancelCtx) String() string {
paddy@0 314 return fmt.Sprintf("%v.WithCancel", c.Context)
paddy@0 315 }
paddy@0 316
paddy@0 317 // cancel closes c.done, cancels each of c's children, and, if
paddy@0 318 // removeFromParent is true, removes c from its parent's children.
paddy@0 319 func (c *cancelCtx) cancel(removeFromParent bool, err error) {
paddy@0 320 if err == nil {
paddy@0 321 panic("context: internal error: missing cancel error")
paddy@0 322 }
paddy@0 323 c.mu.Lock()
paddy@0 324 if c.err != nil {
paddy@0 325 c.mu.Unlock()
paddy@0 326 return // already canceled
paddy@0 327 }
paddy@0 328 c.err = err
paddy@0 329 close(c.done)
paddy@0 330 for child := range c.children {
paddy@0 331 // NOTE: acquiring the child's lock while holding parent's lock.
paddy@0 332 child.cancel(false, err)
paddy@0 333 }
paddy@0 334 c.children = nil
paddy@0 335 c.mu.Unlock()
paddy@0 336
paddy@0 337 if removeFromParent {
paddy@0 338 removeChild(c.Context, c)
paddy@0 339 }
paddy@0 340 }
paddy@0 341
paddy@0 342 // WithDeadline returns a copy of the parent context with the deadline adjusted
paddy@0 343 // to be no later than d. If the parent's deadline is already earlier than d,
paddy@0 344 // WithDeadline(parent, d) is semantically equivalent to parent. The returned
paddy@0 345 // context's Done channel is closed when the deadline expires, when the returned
paddy@0 346 // cancel function is called, or when the parent context's Done channel is
paddy@0 347 // closed, whichever happens first.
paddy@0 348 //
paddy@0 349 // Canceling this context releases resources associated with it, so code should
paddy@0 350 // call cancel as soon as the operations running in this Context complete.
paddy@0 351 func WithDeadline(parent Context, deadline time.Time) (Context, CancelFunc) {
paddy@0 352 if cur, ok := parent.Deadline(); ok && cur.Before(deadline) {
paddy@0 353 // The current deadline is already sooner than the new one.
paddy@0 354 return WithCancel(parent)
paddy@0 355 }
paddy@0 356 c := &timerCtx{
paddy@0 357 cancelCtx: newCancelCtx(parent),
paddy@0 358 deadline: deadline,
paddy@0 359 }
paddy@0 360 propagateCancel(parent, c)
paddy@0 361 d := deadline.Sub(time.Now())
paddy@0 362 if d <= 0 {
paddy@0 363 c.cancel(true, DeadlineExceeded) // deadline has already passed
paddy@0 364 return c, func() { c.cancel(true, Canceled) }
paddy@0 365 }
paddy@0 366 c.mu.Lock()
paddy@0 367 defer c.mu.Unlock()
paddy@0 368 if c.err == nil {
paddy@0 369 c.timer = time.AfterFunc(d, func() {
paddy@0 370 c.cancel(true, DeadlineExceeded)
paddy@0 371 })
paddy@0 372 }
paddy@0 373 return c, func() { c.cancel(true, Canceled) }
paddy@0 374 }
paddy@0 375
paddy@0 376 // A timerCtx carries a timer and a deadline. It embeds a cancelCtx to
paddy@0 377 // implement Done and Err. It implements cancel by stopping its timer then
paddy@0 378 // delegating to cancelCtx.cancel.
paddy@0 379 type timerCtx struct {
paddy@0 380 cancelCtx
paddy@0 381 timer *time.Timer // Under cancelCtx.mu.
paddy@0 382
paddy@0 383 deadline time.Time
paddy@0 384 }
paddy@0 385
paddy@0 386 func (c *timerCtx) Deadline() (deadline time.Time, ok bool) {
paddy@0 387 return c.deadline, true
paddy@0 388 }
paddy@0 389
paddy@0 390 func (c *timerCtx) String() string {
paddy@0 391 return fmt.Sprintf("%v.WithDeadline(%s [%s])", c.cancelCtx.Context, c.deadline, c.deadline.Sub(time.Now()))
paddy@0 392 }
paddy@0 393
paddy@0 394 func (c *timerCtx) cancel(removeFromParent bool, err error) {
paddy@0 395 c.cancelCtx.cancel(false, err)
paddy@0 396 if removeFromParent {
paddy@0 397 // Remove this timerCtx from its parent cancelCtx's children.
paddy@0 398 removeChild(c.cancelCtx.Context, c)
paddy@0 399 }
paddy@0 400 c.mu.Lock()
paddy@0 401 if c.timer != nil {
paddy@0 402 c.timer.Stop()
paddy@0 403 c.timer = nil
paddy@0 404 }
paddy@0 405 c.mu.Unlock()
paddy@0 406 }
paddy@0 407
paddy@0 408 // WithTimeout returns WithDeadline(parent, time.Now().Add(timeout)).
paddy@0 409 //
paddy@0 410 // Canceling this context releases resources associated with it, so code should
paddy@0 411 // call cancel as soon as the operations running in this Context complete:
paddy@0 412 //
paddy@0 413 // func slowOperationWithTimeout(ctx context.Context) (Result, error) {
paddy@0 414 // ctx, cancel := context.WithTimeout(ctx, 100*time.Millisecond)
paddy@0 415 // defer cancel() // releases resources if slowOperation completes before timeout elapses
paddy@0 416 // return slowOperation(ctx)
paddy@0 417 // }
paddy@0 418 func WithTimeout(parent Context, timeout time.Duration) (Context, CancelFunc) {
paddy@0 419 return WithDeadline(parent, time.Now().Add(timeout))
paddy@0 420 }
paddy@0 421
paddy@0 422 // WithValue returns a copy of parent in which the value associated with key is
paddy@0 423 // val.
paddy@0 424 //
paddy@0 425 // Use context Values only for request-scoped data that transits processes and
paddy@0 426 // APIs, not for passing optional parameters to functions.
paddy@0 427 func WithValue(parent Context, key interface{}, val interface{}) Context {
paddy@0 428 return &valueCtx{parent, key, val}
paddy@0 429 }
paddy@0 430
paddy@0 431 // A valueCtx carries a key-value pair. It implements Value for that key and
paddy@0 432 // delegates all other calls to the embedded Context.
paddy@0 433 type valueCtx struct {
paddy@0 434 Context
paddy@0 435 key, val interface{}
paddy@0 436 }
paddy@0 437
paddy@0 438 func (c *valueCtx) String() string {
paddy@0 439 return fmt.Sprintf("%v.WithValue(%#v, %#v)", c.Context, c.key, c.val)
paddy@0 440 }
paddy@0 441
paddy@0 442 func (c *valueCtx) Value(key interface{}) interface{} {
paddy@0 443 if c.key == key {
paddy@0 444 return c.val
paddy@0 445 }
paddy@0 446 return c.Context.Value(key)
paddy@0 447 }