github.com/rahart/packer@v0.12.2-0.20161229105310-282bb6ad370f/builder/azure/common/interruptible_task.go (about)

     1  // Copyright (c) Microsoft Corporation. All rights reserved.
     2  // Licensed under the MIT License. See the LICENSE file in builder/azure for license information.
     3  
     4  package common
     5  
     6  import (
     7  	"time"
     8  )
     9  
    10  type InterruptibleTaskResult struct {
    11  	Err         error
    12  	IsCancelled bool
    13  }
    14  
    15  type InterruptibleTask struct {
    16  	IsCancelled func() bool
    17  	Task        func(cancelCh <-chan struct{}) error
    18  }
    19  
    20  func NewInterruptibleTask(isCancelled func() bool, task func(cancelCh <-chan struct{}) error) *InterruptibleTask {
    21  	return &InterruptibleTask{
    22  		IsCancelled: isCancelled,
    23  		Task:        task,
    24  	}
    25  }
    26  
    27  func StartInterruptibleTask(isCancelled func() bool, task func(cancelCh <-chan struct{}) error) InterruptibleTaskResult {
    28  	t := NewInterruptibleTask(isCancelled, task)
    29  	return t.Run()
    30  }
    31  
    32  func (s *InterruptibleTask) Run() InterruptibleTaskResult {
    33  	completeCh := make(chan error)
    34  
    35  	cancelCh := make(chan struct{})
    36  	defer close(cancelCh)
    37  
    38  	go func() {
    39  		err := s.Task(cancelCh)
    40  		completeCh <- err
    41  
    42  		// senders close, receivers check for close
    43  		close(completeCh)
    44  	}()
    45  
    46  	for {
    47  		if s.IsCancelled() {
    48  			return InterruptibleTaskResult{Err: nil, IsCancelled: true}
    49  		}
    50  
    51  		select {
    52  		case err := <-completeCh:
    53  			return InterruptibleTaskResult{Err: err, IsCancelled: false}
    54  		case <-time.After(100 * time.Millisecond):
    55  		}
    56  	}
    57  }