github.com/hs0210/hashicorp-terraform@v0.11.12-beta1/helper/shadow/ordered_value.go (about) 1 package shadow 2 3 import ( 4 "container/list" 5 "sync" 6 ) 7 8 // OrderedValue is a struct that keeps track of a value in the order 9 // it is set. Each time Value() is called, it will return the most recent 10 // calls value then discard it. 11 // 12 // This is unlike Value that returns the same value once it is set. 13 type OrderedValue struct { 14 lock sync.Mutex 15 values *list.List 16 waiters *list.List 17 } 18 19 // Value returns the last value that was set, or blocks until one 20 // is received. 21 func (w *OrderedValue) Value() interface{} { 22 w.lock.Lock() 23 24 // If we have a pending value already, use it 25 if w.values != nil && w.values.Len() > 0 { 26 front := w.values.Front() 27 w.values.Remove(front) 28 w.lock.Unlock() 29 return front.Value 30 } 31 32 // No pending value, create a waiter 33 if w.waiters == nil { 34 w.waiters = list.New() 35 } 36 37 var val Value 38 w.waiters.PushBack(&val) 39 w.lock.Unlock() 40 41 // Return the value once we have it 42 return val.Value() 43 } 44 45 // SetValue sets the latest value. 46 func (w *OrderedValue) SetValue(v interface{}) { 47 w.lock.Lock() 48 defer w.lock.Unlock() 49 50 // If we have a waiter, notify it 51 if w.waiters != nil && w.waiters.Len() > 0 { 52 front := w.waiters.Front() 53 w.waiters.Remove(front) 54 55 val := front.Value.(*Value) 56 val.SetValue(v) 57 return 58 } 59 60 // Add it to the list of values 61 if w.values == nil { 62 w.values = list.New() 63 } 64 65 w.values.PushBack(v) 66 }