-
Notifications
You must be signed in to change notification settings - Fork 0
/
lazy.go
66 lines (57 loc) · 1.78 KB
/
lazy.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
//spellchecker:words lazy
package lazy
//spellchecker:words sync
import (
"sync"
)
// Lazy holds a lazily initialized value of T.
// A non-zero lazy must not be copied after first use.
//
// Lazy should be used where a single value is initialized and reset at different call sites with undefined order and values.
// A value initialized in one place and read many times should use [sync.OnceValue] instead.
type Lazy[T any] struct {
m sync.Mutex // m protects the value of this lazy
done bool // is a value stored?
value T // the held value
}
// Get returns the value associated with this Lazy.
//
// If no other call to Get has started or completed an initialization, calls init to initialize the value.
// A nil init function indicates to store the zero value of T.
// If an initialization has been previously completed, the previously stored value is returned.
//
// If init panics, the initialization is considered to be completed.
// Future calls to Get() do not invoke init, and the zero value of T is returned.
//
// Get may safely be called concurrently.
func (lazy *Lazy[T]) Get(init func() T) T {
if lazy == nil {
panic("attempt to access (*Lazy[...])(nil)")
}
lazy.m.Lock()
defer lazy.m.Unlock()
// value is not yet initialized
if !lazy.done {
lazy.done = true
if init != nil {
lazy.value = init()
}
}
// and return the value!
return lazy.value
}
// Set atomically sets the value of this lazy.
// Any previously set value will be overwritten.
// Future calls to [Get] will not invoke init.
//
// It may be called concurrently with calls to [Get].
func (lazy *Lazy[T]) Set(value T) {
if lazy == nil {
panic("attempt to access (*Lazy[...])(nil)")
}
lazy.m.Lock()
defer lazy.m.Unlock()
// we store the value now!
lazy.done = true
lazy.value = value
}