]>
Commit | Line | Data |
---|---|---|
bae9f6d2 JC |
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 | ||
c680a8e1 RS |
29 | func (v *Value) Lock() { |
30 | v.lock.Lock() | |
31 | } | |
32 | ||
33 | func (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. | |
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 | } |