7 // ComparedValue is a struct that finds a value by comparing some key
8 // to the list of stored values. This is useful when there is no easy
9 // uniquely identifying key that works in a map (for that, use KeyedValue).
11 // ComparedValue is very expensive, relative to other Value types. Try to
12 // limit the number of values stored in a ComparedValue by potentially
13 // nesting it within a KeyedValue (a keyed value points to a compared value,
15 type ComparedValue struct {
16 // Func is a function that is given the lookup key and a single
17 // stored value. If it matches, it returns true.
18 Func func(k, v interface{}) bool
24 waiters map[interface{}]*Value
27 // Close closes the value. This can never fail. For a definition of
28 // "close" see the ErrClosed docs.
29 func (w *ComparedValue) Close() error {
33 // Set closed to true always
36 // For all waiters, complete with ErrClosed
37 for k, val := range w.waiters {
38 val.SetValue(ErrClosed)
45 // Value returns the value that was set for the given key, or blocks
46 // until one is available.
47 func (w *ComparedValue) Value(k interface{}) interface{} {
48 v, val := w.valueWaiter(k)
56 // ValueOk gets the value for the given key, returning immediately if the
57 // value doesn't exist. The second return argument is true if the value exists.
58 func (w *ComparedValue) ValueOk(k interface{}) (interface{}, bool) {
59 v, val := w.valueWaiter(k)
63 func (w *ComparedValue) SetValue(v interface{}) {
68 // Check if we already have this exact value (by simply comparing
69 // with == directly). If we do, then we don't insert it again.
71 for _, v2 := range w.values {
79 // Set the value, always
80 w.values = append(w.values, v)
83 // Go through the waiters
84 for k, val := range w.waiters {
92 func (w *ComparedValue) valueWaiter(k interface{}) (interface{}, *Value) {
96 // Look for a pre-existing value
97 for _, v := range w.values {
104 // If we're closed, return that
107 return ErrClosed, nil
110 // Pre-existing value doesn't exist, create a waiter
122 // Must be called with w.lock held.
123 func (w *ComparedValue) init() {
124 w.waiters = make(map[interface{}]*Value)
126 w.Func = func(k, v interface{}) bool { return k == v }