code: func Retry(timeout time.Duration, f RetryFunc) error {
  	// These are used to pull the error out of the function; need a mutex to
  	// avoid a data race.
  	var resultErr error
  	var resultErrMu sync.Mutex
  
  	c := &StateChangeConf{
  		Pending:    []string{"retryableerror"},
  		Target:     []string{"success"},
  		Timeout:    timeout,
  		MinTimeout: 500 * time.Millisecond,
  		Refresh: func() (interface{}, string, error) {
  			rerr := f()
  
  			resultErrMu.Lock()
  			defer resultErrMu.Unlock()
  
  			if rerr == nil {
  				resultErr = nil
  				return 42, "success", nil
  			}
  
  			resultErr = rerr.Err
  
  			if rerr.Retryable {
  				return 42, "retryableerror", nil
  			}
  			return nil, "quit", rerr.Err
  		},
  	}
  
  	_, waitErr := c.WaitForState()
  
  	// Need to acquire the lock here to be able to avoid race using resultErr as
  	// the return value
  	resultErrMu.Lock()
  	defer resultErrMu.Unlock()
  
  	// resultErr may be nil because the wait timed out and resultErr was never
  	// set; this is still an error
  	if resultErr == nil {
  		return waitErr
  	}
  	// resultErr takes precedence over waitErr if both are set because it is
  	// more likely to be useful
  	return resultErr
  }
docs: // Retry is a basic wrapper around StateChangeConf that will just retry
  // a function until it no longer returns an error.