github.com/dougneal/terraform@v0.6.15-0.20170330092735-b6a3840768a4/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  }