helper/shadow: KeyedValue.WaitForChange

This commit is contained in:
Mitchell Hashimoto 2016-10-05 12:54:53 -07:00
parent 184b4a8b09
commit 0408c2dfb2
No known key found for this signature in database
GPG Key ID: 744E147AA52F5B0A
2 changed files with 75 additions and 0 deletions

View File

@ -42,6 +42,26 @@ func (w *KeyedValue) Value(k string) interface{} {
return val.Value()
}
// WaitForChange waits for the value with the given key to be set again.
// If the key isn't set, it'll wait for an initial value. Note that while
// it is called "WaitForChange", the value isn't guaranteed to _change_;
// this will return when a SetValue is called for the given k.
func (w *KeyedValue) WaitForChange(k string) interface{} {
w.lock.Lock()
w.once.Do(w.init)
// Check for an active waiter. If there isn't one, make it
val := w.waiters[k]
if val == nil {
val = new(Value)
w.waiters[k] = val
}
w.lock.Unlock()
// And wait
return val.Value()
}
// ValueOk gets the value for the given key, returning immediately if the
// value doesn't exist. The second return argument is true if the value exists.
func (w *KeyedValue) ValueOk(k string) (interface{}, bool) {

View File

@ -168,3 +168,58 @@ func TestKeyedValueClose_existingBlocked(t *testing.T) {
t.Fatalf("bad: %#v", val)
}
}
func TestKeyedValueWaitForChange(t *testing.T) {
var v KeyedValue
// Set a value
v.SetValue("foo", 42)
// Start reading this should be blocking
valueCh := make(chan interface{})
go func() {
valueCh <- v.WaitForChange("foo")
}()
// We should not get the value
select {
case <-valueCh:
t.Fatal("shouldn't receive value")
case <-time.After(10 * time.Millisecond):
}
// Set a new value
v.SetValue("foo", 84)
// Verify
val := <-valueCh
if val != 84 {
t.Fatalf("bad: %#v", val)
}
}
func TestKeyedValueWaitForChange_initial(t *testing.T) {
var v KeyedValue
// Start reading this should be blocking
valueCh := make(chan interface{})
go func() {
valueCh <- v.WaitForChange("foo")
}()
// We should not get the value
select {
case <-valueCh:
t.Fatal("shouldn't receive value")
case <-time.After(10 * time.Millisecond):
}
// Set a new value
v.SetValue("foo", 84)
// Verify
val := <-valueCh
if val != 84 {
t.Fatalf("bad: %#v", val)
}
}