// Do sends an HTTP request with the provided http.Client and returns an HTTP response. // If the client is nil, http.DefaultClient is used. // If the context is canceled or times out, ctx.Err() will be returned. func Do(ctx context.Context, client *http.Client, req *http.Request) (*http.Response, error) { if client == nil { client = http.DefaultClient } // Request cancelation changed in Go 1.5, see cancelreq.go and cancelreq_go14.go. cancel := canceler(client, req) type responseAndError struct { resp *http.Response err error } result := make(chan responseAndError, 1) go func() { resp, err := client.Do(req) result <- responseAndError{resp, err} }() select { case <-ctx.Done(): cancel() return nil, ctx.Err() case r := <-result: return r.resp, r.err } }
// Wait blocks until i) the new transport is up or ii) ctx is done or iii) cc is closed. func (cc *Conn) Wait(ctx context.Context) (transport.ClientTransport, error) { for { cc.mu.Lock() switch { case cc.state == Shutdown: cc.mu.Unlock() return nil, ErrClientConnClosing case cc.state == Ready: cc.mu.Unlock() return cc.transport, nil default: ready := cc.ready if ready == nil { ready = make(chan struct{}) cc.ready = ready } cc.mu.Unlock() select { case <-ctx.Done(): return nil, transport.ContextErr(ctx.Err()) // Wait until the new transport is ready or failed. case <-ready: } } } }
func (w *watcher) Next(ctx context.Context) (nu []*naming.Update, err error) { once.Do(func() { select { case <-ctx.Done(): err = ctx.Err() default: for _, v := range w.kv { nu = append(nu, &naming.Update{ Op: naming.Add, Addr: v, }) } } }) if len(nu) > 0 || err != nil { // once.Do ran. Return directly. return } for { resp, err := w.wr.Next(ctx) if err != nil { return nil, err } if resp.Node.Dir { continue } w.mu.Lock() switch resp.Action { case "set": if resp.PrevNode == nil { nu = append(nu, &naming.Update{ Op: naming.Add, Addr: resp.Node.Value, }) w.kv[resp.Node.Key] = resp.Node.Value } else { nu = append(nu, &naming.Update{ Op: naming.Delete, Addr: w.kv[resp.Node.Key], }) nu = append(nu, &naming.Update{ Op: naming.Add, Addr: resp.Node.Value, }) w.kv[resp.Node.Key] = resp.Node.Value } case "delete": nu = append(nu, &naming.Update{ Op: naming.Delete, Addr: resp.Node.Value, }) delete(w.kv, resp.Node.Key) } w.mu.Unlock() return nu, nil } }
// wait blocks until it can receive from ctx.Done, closing, or proceed. // If it receives from ctx.Done, it returns 0, the StreamError for ctx.Err. // If it receives from closing, it returns 0, ErrConnClosing. // If it receives from proceed, it returns the received integer, nil. func wait(ctx context.Context, closing <-chan struct{}, proceed <-chan int) (int, error) { select { case <-ctx.Done(): return 0, ContextErr(ctx.Err()) case <-closing: return 0, ErrConnClosing case i := <-proceed: return i, nil } }