github.com/getlantern/eventual@v1.0.0/eventual.go (about) 1 // Package eventual provides values that eventually have a value. 2 package eventual 3 4 import ( 5 "math" 6 "sync" 7 "sync/atomic" 8 "time" 9 ) 10 11 const ( 12 // Forever indicates that Get should wait forever 13 Forever = -1 14 ) 15 16 // Value is an eventual value, meaning that callers wishing to access the value 17 // block until the value is available. 18 type Value interface { 19 // Set sets this Value to the given val. 20 Set(val interface{}) 21 22 // Get waits up to timeout for the value to be set and returns it, or returns 23 // nil if it times out or Cancel() is called. valid will be false in latter 24 // case. If timeout is 0, Get won't wait. If timeout is -1, Get will wait 25 // forever. 26 Get(timeout time.Duration) (ret interface{}, valid bool) 27 28 // Cancel cancels this value, signaling any waiting calls to Get() that no 29 // value is coming. If no value was set before Cancel() was called, all future 30 // calls to Get() will return nil, false. Subsequent calls to Set after Cancel 31 // have no effect. 32 Cancel() 33 } 34 35 // Getter is a functional interface for the Value.Get function 36 type Getter func(time.Duration) (interface{}, bool) 37 38 type value struct { 39 state atomic.Value 40 waiters []chan interface{} 41 mutex sync.Mutex 42 } 43 44 type stateholder struct { 45 val interface{} 46 set bool 47 canceled bool 48 } 49 50 // NewValue creates a new Value. 51 func NewValue() Value { 52 result := &value{waiters: make([]chan interface{}, 0)} 53 result.state.Store(&stateholder{}) 54 return result 55 } 56 57 // DefaultGetter builds a Getter that always returns the supplied value. 58 func DefaultGetter(val interface{}) Getter { 59 return func(time.Duration) (interface{}, bool) { 60 return val, true 61 } 62 } 63 64 // DefaultUnsetGetter builds a Getter that always !ok. 65 func DefaultUnsetGetter() Getter { 66 return func(time.Duration) (interface{}, bool) { 67 return nil, false 68 } 69 } 70 71 func (v *value) Set(val interface{}) { 72 v.mutex.Lock() 73 defer v.mutex.Unlock() 74 75 state := v.getState() 76 settable := !state.canceled 77 if settable { 78 v.setState(&stateholder{ 79 val: val, 80 set: true, 81 canceled: false, 82 }) 83 84 if v.waiters != nil { 85 // Notify anyone waiting for value 86 for _, waiter := range v.waiters { 87 waiter <- val 88 } 89 // Clear waiters 90 v.waiters = nil 91 } 92 } 93 } 94 95 func (v *value) Cancel() { 96 v.mutex.Lock() 97 defer v.mutex.Unlock() 98 99 state := v.getState() 100 v.setState(&stateholder{ 101 val: state.val, 102 set: state.set, 103 canceled: true, 104 }) 105 106 if v.waiters != nil { 107 // Notify anyone waiting for value 108 for _, waiter := range v.waiters { 109 close(waiter) 110 } 111 // Clear waiters 112 v.waiters = nil 113 } 114 } 115 116 func (v *value) Get(timeout time.Duration) (ret interface{}, valid bool) { 117 state := v.getState() 118 119 // First check for existing value using atomic operations (for speed) 120 if state.set { 121 // Value found, use it 122 return state.val, true 123 } else if state.canceled { 124 // Value was canceled, return false 125 return nil, false 126 } 127 128 if timeout == 0 { 129 // Don't wait 130 return nil, false 131 } 132 133 // If we didn't find an existing value, try again but this time using locking 134 v.mutex.Lock() 135 state = v.getState() 136 137 if state.set { 138 // Value found, use it 139 v.mutex.Unlock() 140 return state.val, true 141 } else if state.canceled { 142 // Value was canceled, return false 143 v.mutex.Unlock() 144 return nil, false 145 } 146 147 if timeout == -1 { 148 // Wait essentially forever 149 timeout = time.Duration(math.MaxInt64) 150 } 151 152 // Value not found, register to be notified once value is set 153 valCh := make(chan interface{}, 1) 154 v.waiters = append(v.waiters, valCh) 155 v.mutex.Unlock() 156 157 // Wait up to timeout for value to get set 158 select { 159 case v, ok := <-valCh: 160 return v, ok 161 case <-time.After(timeout): 162 return nil, false 163 } 164 } 165 166 func (v *value) getState() *stateholder { 167 state := v.state.Load() 168 if state == nil { 169 return nil 170 } 171 return state.(*stateholder) 172 } 173 174 func (v *value) setState(state *stateholder) { 175 v.state.Store(state) 176 }