]> git.immae.eu Git - github/fretlink/terraform-provider-statuscake.git/blame - vendor/github.com/hashicorp/terraform/helper/shadow/value.go
vendor: github.com/hashicorp/terraform/...@v0.10.0
[github/fretlink/terraform-provider-statuscake.git] / vendor / github.com / hashicorp / terraform / helper / shadow / value.go
CommitLineData
bae9f6d2
JC
1package shadow
2
3import (
4 "errors"
5 "sync"
6)
7
8// ErrClosed is returned by any closed values.
9//
10// A "closed value" is when the shadow has been notified that the real
11// side is complete and any blocking values will _never_ be satisfied
12// in the future. In this case, this error is returned. If a value is already
13// available, that is still returned.
14var ErrClosed = errors.New("shadow closed")
15
16// Value is a struct that coordinates a value between two
17// parallel routines. It is similar to atomic.Value except that when
18// Value is called if it isn't set it will wait for it.
19//
20// The Value can be closed with Close, which will cause any future
21// blocking operations to return immediately with ErrClosed.
22type Value struct {
23 lock sync.Mutex
24 cond *sync.Cond
25 value interface{}
26 valueSet bool
27}
28
c680a8e1
RS
29func (v *Value) Lock() {
30 v.lock.Lock()
31}
32
33func (v *Value) Unlock() {
34 v.lock.Unlock()
35}
36
bae9f6d2
JC
37// Close closes the value. This can never fail. For a definition of
38// "close" see the struct docs.
39func (w *Value) Close() error {
40 w.lock.Lock()
41 set := w.valueSet
42 w.lock.Unlock()
43
44 // If we haven't set the value, set it
45 if !set {
46 w.SetValue(ErrClosed)
47 }
48
49 // Done
50 return nil
51}
52
53// Value returns the value that was set.
54func (w *Value) Value() interface{} {
55 w.lock.Lock()
56 defer w.lock.Unlock()
57
58 // If we already have a value just return
59 for !w.valueSet {
60 // No value, setup the condition variable if we have to
61 if w.cond == nil {
62 w.cond = sync.NewCond(&w.lock)
63 }
64
65 // Wait on it
66 w.cond.Wait()
67 }
68
69 // Return the value
70 return w.value
71}
72
73// SetValue sets the value.
74func (w *Value) SetValue(v interface{}) {
75 w.lock.Lock()
76 defer w.lock.Unlock()
77
78 // Set the value
79 w.valueSet = true
80 w.value = v
81
82 // If we have a condition, clear it
83 if w.cond != nil {
84 w.cond.Broadcast()
85 w.cond = nil
86 }
87}