]> git.immae.eu Git - github/fretlink/terraform-provider-statuscake.git/blob - 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
1 package shadow
2
3 import (
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.
14 var 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.
22 type Value struct {
23 lock sync.Mutex
24 cond *sync.Cond
25 value interface{}
26 valueSet bool
27 }
28
29 func (v *Value) Lock() {
30 v.lock.Lock()
31 }
32
33 func (v *Value) Unlock() {
34 v.lock.Unlock()
35 }
36
37 // Close closes the value. This can never fail. For a definition of
38 // "close" see the struct docs.
39 func (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.
54 func (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.
74 func (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 }