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 }