]> git.immae.eu Git - github/fretlink/terraform-provider-statuscake.git/blob - vendor/github.com/hashicorp/terraform/helper/shadow/value.go
2413335b801a075cb1a7cf87ad7faec806f6ddff
[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 // Close closes the value. This can never fail. For a definition of
30 // "close" see the struct docs.
31 func (w *Value) Close() error {
32 w.lock.Lock()
33 set := w.valueSet
34 w.lock.Unlock()
35
36 // If we haven't set the value, set it
37 if !set {
38 w.SetValue(ErrClosed)
39 }
40
41 // Done
42 return nil
43 }
44
45 // Value returns the value that was set.
46 func (w *Value) Value() interface{} {
47 w.lock.Lock()
48 defer w.lock.Unlock()
49
50 // If we already have a value just return
51 for !w.valueSet {
52 // No value, setup the condition variable if we have to
53 if w.cond == nil {
54 w.cond = sync.NewCond(&w.lock)
55 }
56
57 // Wait on it
58 w.cond.Wait()
59 }
60
61 // Return the value
62 return w.value
63 }
64
65 // SetValue sets the value.
66 func (w *Value) SetValue(v interface{}) {
67 w.lock.Lock()
68 defer w.lock.Unlock()
69
70 // Set the value
71 w.valueSet = true
72 w.value = v
73
74 // If we have a condition, clear it
75 if w.cond != nil {
76 w.cond.Broadcast()
77 w.cond = nil
78 }
79 }