github.com/makyo/juju@v0.0.0-20160425123129-2608902037e9/cmd/jujud/agent/util/valueworker.go (about) 1 // Copyright 2016 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 // NewValueWorker returns a degenerate worker that exposes the supplied value 16 // when passed into ValueWorkerOutput. Please do not supply values that have 17 // their own dependency or lifecycle considerations; such values will subvert 18 // the operation of any containing dependency.Engine by insulating it from the 19 // failures and dependency changes of the contained value. 20 func NewValueWorker(value interface{}) (worker.Worker, error) { 21 if value == nil { 22 return nil, errors.New("NewValueWorker expects a value") 23 } 24 w := &valueWorker{ 25 value: value, 26 } 27 go func() { 28 defer w.tomb.Done() 29 <-w.tomb.Dying() 30 }() 31 return w, nil 32 } 33 34 // ValueWorkerOutput sets the value wrapped by the supplied valueWorker into 35 // the out pointer, if type-compatible, or fails. 36 func ValueWorkerOutput(in worker.Worker, out interface{}) error { 37 inWorker, _ := in.(*valueWorker) 38 if inWorker == nil { 39 return errors.Errorf("in should be a *valueWorker; is %#v", in) 40 } 41 outV := reflect.ValueOf(out) 42 if outV.Kind() != reflect.Ptr { 43 return errors.Errorf("out should be a pointer; is %#v", out) 44 } 45 outValV := outV.Elem() 46 outValT := outValV.Type() 47 inValV := reflect.ValueOf(inWorker.value) 48 inValT := inValV.Type() 49 if !inValT.ConvertibleTo(outValT) { 50 return errors.Errorf("cannot output into %T", out) 51 } 52 outValV.Set(inValV.Convert(outValT)) 53 return nil 54 } 55 56 // valueWorker implements a degenerate worker wrapping a single value. 57 type valueWorker struct { 58 tomb tomb.Tomb 59 value interface{} 60 } 61 62 // Kill is part of the worker.Worker interface. 63 func (v *valueWorker) Kill() { 64 v.tomb.Kill(nil) 65 } 66 67 // Wait is part of the worker.Worker interface. 68 func (v *valueWorker) Wait() error { 69 return v.tomb.Wait() 70 }