summaryrefslogtreecommitdiff
path: root/vendor/github.com/hashicorp/terraform/helper/shadow/value.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/hashicorp/terraform/helper/shadow/value.go')
-rw-r--r--vendor/github.com/hashicorp/terraform/helper/shadow/value.go79
1 files changed, 79 insertions, 0 deletions
diff --git a/vendor/github.com/hashicorp/terraform/helper/shadow/value.go b/vendor/github.com/hashicorp/terraform/helper/shadow/value.go
new file mode 100644
index 00000000..2413335b
--- /dev/null
+++ b/vendor/github.com/hashicorp/terraform/helper/shadow/value.go
@@ -0,0 +1,79 @@
+package shadow
+
+import (
+ "errors"
+ "sync"
+)
+
+// ErrClosed is returned by any closed values.
+//
+// A "closed value" is when the shadow has been notified that the real
+// side is complete and any blocking values will _never_ be satisfied
+// in the future. In this case, this error is returned. If a value is already
+// available, that is still returned.
+var ErrClosed = errors.New("shadow closed")
+
+// Value is a struct that coordinates a value between two
+// parallel routines. It is similar to atomic.Value except that when
+// Value is called if it isn't set it will wait for it.
+//
+// The Value can be closed with Close, which will cause any future
+// blocking operations to return immediately with ErrClosed.
+type Value struct {
+ lock sync.Mutex
+ cond *sync.Cond
+ value interface{}
+ valueSet bool
+}
+
+// Close closes the value. This can never fail. For a definition of
+// "close" see the struct docs.
+func (w *Value) Close() error {
+ w.lock.Lock()
+ set := w.valueSet
+ w.lock.Unlock()
+
+ // If we haven't set the value, set it
+ if !set {
+ w.SetValue(ErrClosed)
+ }
+
+ // Done
+ return nil
+}
+
+// Value returns the value that was set.
+func (w *Value) Value() interface{} {
+ w.lock.Lock()
+ defer w.lock.Unlock()
+
+ // If we already have a value just return
+ for !w.valueSet {
+ // No value, setup the condition variable if we have to
+ if w.cond == nil {
+ w.cond = sync.NewCond(&w.lock)
+ }
+
+ // Wait on it
+ w.cond.Wait()
+ }
+
+ // Return the value
+ return w.value
+}
+
+// SetValue sets the value.
+func (w *Value) SetValue(v interface{}) {
+ w.lock.Lock()
+ defer w.lock.Unlock()
+
+ // Set the value
+ w.valueSet = true
+ w.value = v
+
+ // If we have a condition, clear it
+ if w.cond != nil {
+ w.cond.Broadcast()
+ w.cond = nil
+ }
+}