github.com/mhilton/juju-juju@v0.0.0-20150901100907-a94dd2c73455/worker/util/valueworker.go (about)

     1  // Copyright 2015 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package util
     5  
     6  import (
     7  	"reflect"
     8  
     9  	"github.com/juju/errors"
    10  	"launchpad.net/tomb"
    11  
    12  	"github.com/juju/juju/worker"
    13  )
    14  
    15  // valueWorker implements a degenerate worker wrapping a single value.
    16  type valueWorker struct {
    17  	tomb  tomb.Tomb
    18  	value interface{}
    19  }
    20  
    21  // Kill is part of the worker.Worker interface.
    22  func (v *valueWorker) Kill() {
    23  	v.tomb.Kill(nil)
    24  }
    25  
    26  // Wait is part of the worker.Worker interface.
    27  func (v *valueWorker) Wait() error {
    28  	return v.tomb.Wait()
    29  }
    30  
    31  // NewValueWorker returns a degenerate worker that exposes the supplied value
    32  // when passed into ValueWorkerOutput.
    33  func NewValueWorker(value interface{}) (worker.Worker, error) {
    34  	if value == nil {
    35  		return nil, errors.New("NewValueWorker expects a value")
    36  	}
    37  	w := &valueWorker{
    38  		value: value,
    39  	}
    40  	go func() {
    41  		defer w.tomb.Done()
    42  		<-w.tomb.Dying()
    43  	}()
    44  	return w, nil
    45  }
    46  
    47  // ValueWorkerOutput sets the value wrapped by the supplied valueWorker into
    48  // the out pointer, if type-compatible, or fails.
    49  func ValueWorkerOutput(in worker.Worker, out interface{}) error {
    50  	inWorker, _ := in.(*valueWorker)
    51  	if inWorker == nil {
    52  		return errors.Errorf("in should be a *valueWorker; is %#v", in)
    53  	}
    54  	outV := reflect.ValueOf(out)
    55  	if outV.Kind() != reflect.Ptr {
    56  		return errors.Errorf("out should be a pointer; is %#v", out)
    57  	}
    58  	outValV := outV.Elem()
    59  	outValT := outValV.Type()
    60  	inValV := reflect.ValueOf(inWorker.value)
    61  	inValT := inValV.Type()
    62  	if !inValT.ConvertibleTo(outValT) {
    63  		return errors.Errorf("cannot output into %T", out)
    64  	}
    65  	outValV.Set(inValV.Convert(outValT))
    66  	return nil
    67  }