opentofu/helper/shadow/ordered_value.go
2016-10-11 22:17:27 +08:00

67 lines
1.3 KiB
Go

package shadow
import (
"container/list"
"sync"
)
// OrderedValue is a struct that keeps track of a value in the order
// it is set. Each time Value() is called, it will return the most recent
// calls value then discard it.
//
// This is unlike Value that returns the same value once it is set.
type OrderedValue struct {
lock sync.Mutex
values *list.List
waiters *list.List
}
// Value returns the last value that was set, or blocks until one
// is received.
func (w *OrderedValue) Value() interface{} {
w.lock.Lock()
// If we have a pending value already, use it
if w.values != nil && w.values.Len() > 0 {
front := w.values.Front()
w.values.Remove(front)
w.lock.Unlock()
return front.Value
}
// No pending value, create a waiter
if w.waiters == nil {
w.waiters = list.New()
}
var val Value
w.waiters.PushBack(&val)
w.lock.Unlock()
// Return the value once we have it
return val.Value()
}
// SetValue sets the latest value.
func (w *OrderedValue) SetValue(v interface{}) {
w.lock.Lock()
defer w.lock.Unlock()
// If we have a waiter, notify it
if w.waiters != nil && w.waiters.Len() > 0 {
front := w.waiters.Front()
w.waiters.Remove(front)
val := front.Value.(*Value)
val.SetValue(v)
return
}
// Add it to the list of values
if w.values == nil {
w.values = list.New()
}
w.values.PushBack(v)
}