-
Notifications
You must be signed in to change notification settings - Fork 9.5k
/
ordered_value.go
66 lines (54 loc) · 1.33 KB
/
ordered_value.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
package shadow
import (
"container/list"
"sync"
)
// OrderedValue is a struct that keeps track of a value in the order
// it is set. Each time Value() is called, it will return the most recent
// calls value then discard it.
//
// This is unlike Value that returns the same value once it is set.
type OrderedValue struct {
lock sync.Mutex
values *list.List
waiters *list.List
}
// Value returns the last value that was set, or blocks until one
// is received.
func (w *OrderedValue) Value() interface{} {
w.lock.Lock()
// If we have a pending value already, use it
if w.values != nil && w.values.Len() > 0 {
front := w.values.Front()
w.values.Remove(front)
w.lock.Unlock()
return front.Value
}
// No pending value, create a waiter
if w.waiters == nil {
w.waiters = list.New()
}
var val Value
w.waiters.PushBack(&val)
w.lock.Unlock()
// Return the value once we have it
return val.Value()
}
// SetValue sets the latest value.
func (w *OrderedValue) SetValue(v interface{}) {
w.lock.Lock()
defer w.lock.Unlock()
// If we have a waiter, notify it
if w.waiters != nil && w.waiters.Len() > 0 {
front := w.waiters.Front()
w.waiters.Remove(front)
val := front.Value.(*Value)
val.SetValue(v)
return
}
// Add it to the list of values
if w.values == nil {
w.values = list.New()
}
w.values.PushBack(v)
}