github.com/mmcquillan/packer@v1.1.1-0.20171009221028-c85cf0483a5d/builder/azure/common/interruptible_task.go (about) 1 package common 2 3 import ( 4 "time" 5 ) 6 7 type InterruptibleTaskResult struct { 8 Err error 9 IsCancelled bool 10 } 11 12 type InterruptibleTask struct { 13 IsCancelled func() bool 14 Task func(cancelCh <-chan struct{}) error 15 } 16 17 func NewInterruptibleTask(isCancelled func() bool, task func(cancelCh <-chan struct{}) error) *InterruptibleTask { 18 return &InterruptibleTask{ 19 IsCancelled: isCancelled, 20 Task: task, 21 } 22 } 23 24 func StartInterruptibleTask(isCancelled func() bool, task func(cancelCh <-chan struct{}) error) InterruptibleTaskResult { 25 t := NewInterruptibleTask(isCancelled, task) 26 return t.Run() 27 } 28 29 func (s *InterruptibleTask) Run() InterruptibleTaskResult { 30 completeCh := make(chan error) 31 32 cancelCh := make(chan struct{}) 33 defer close(cancelCh) 34 35 go func() { 36 err := s.Task(cancelCh) 37 completeCh <- err 38 39 // senders close, receivers check for close 40 close(completeCh) 41 }() 42 43 for { 44 if s.IsCancelled() { 45 return InterruptibleTaskResult{Err: nil, IsCancelled: true} 46 } 47 48 select { 49 case err := <-completeCh: 50 return InterruptibleTaskResult{Err: err, IsCancelled: false} 51 case <-time.After(100 * time.Millisecond): 52 } 53 } 54 }