From ba7c5ddcd2803d77653e1cc4b0f046efe8231058 Mon Sep 17 00:00:00 2001 From: Cheng Sun Date: Tue, 9 Dec 2014 14:55:35 +0000 Subject: [PATCH] interruptible_wait: allow nil Predicate Allow for the case where InterruptibleWait is used purely for the timeout. See the documentation string for details. --- builder/xenserver/interruptible_wait.go | 44 ++++++++++++++++--------- 1 file changed, 29 insertions(+), 15 deletions(-) diff --git a/builder/xenserver/interruptible_wait.go b/builder/xenserver/interruptible_wait.go index 9757377..8ad7f6f 100644 --- a/builder/xenserver/interruptible_wait.go +++ b/builder/xenserver/interruptible_wait.go @@ -6,9 +6,11 @@ import ( ) type InterruptibleWait struct { + Timeout time.Duration + + // optional: Predicate func() (result bool, err error) PredicateInterval time.Duration - Timeout time.Duration } type TimeoutError struct{} @@ -28,26 +30,34 @@ type PredicateResult struct { err error } +/* Wait waits for up to Timeout duration, checking an optional Predicate every PredicateInterval duration. + The first run of Predicate is immediately after Wait is called. + If the command is interrupted by the user, then an InterruptedError is returned. + If Predicate is not nil, a timeout leads to TimeoutError being returned, and a successful Predicate run leads to nil being returned. + If Predicate is nil, a timeout is not an error, and nil is returned. +*/ func (wait InterruptibleWait) Wait(state multistep.StateBag) error { predicateResult := make(chan PredicateResult, 1) stopWaiting := make(chan struct{}) defer close(stopWaiting) - go func() { - for { - if complete, err := wait.Predicate(); err != nil || complete { - predicateResult <- PredicateResult{complete, err} - return - } + if wait.Predicate != nil { + go func() { + for { + if complete, err := wait.Predicate(); err != nil || complete { + predicateResult <- PredicateResult{complete, err} + return + } - select { - case <-time.After(wait.PredicateInterval): - // do nothing; loop again - case <-stopWaiting: - return + select { + case <-time.After(wait.PredicateInterval): + // do nothing; loop again + case <-stopWaiting: + return + } } - } - }() + }() + } timeout := time.After(wait.Timeout) for { @@ -63,7 +73,11 @@ func (wait InterruptibleWait) Wait(state multistep.StateBag) error { } case <-timeout: - return TimeoutError{} + if wait.Predicate != nil { + return TimeoutError{} + } else { + return nil + } } } }