aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'android/onceper.go')
-rw-r--r--android/onceper.go16
1 files changed, 11 insertions, 5 deletions
diff --git a/android/onceper.go b/android/onceper.go
index 5ad17fa9..ff865c2e 100644
--- a/android/onceper.go
+++ b/android/onceper.go
@@ -40,7 +40,8 @@ func (once *OncePer) maybeWaitFor(key OnceKey, value interface{}) interface{} {
40} 40}
41 41
42// Once computes a value the first time it is called with a given key per OncePer, and returns the 42// Once computes a value the first time it is called with a given key per OncePer, and returns the
43// value without recomputing when called with the same key. key must be hashable. 43// value without recomputing when called with the same key. key must be hashable. If value panics
44// the panic will be propagated but the next call to Once with the same key will return nil.
44func (once *OncePer) Once(key OnceKey, value func() interface{}) interface{} { 45func (once *OncePer) Once(key OnceKey, value func() interface{}) interface{} {
45 // Fast path: check if the key is already in the map 46 // Fast path: check if the key is already in the map
46 if v, ok := once.values.Load(key); ok { 47 if v, ok := once.values.Load(key); ok {
@@ -54,10 +55,15 @@ func (once *OncePer) Once(key OnceKey, value func() interface{}) interface{} {
54 return once.maybeWaitFor(key, v) 55 return once.maybeWaitFor(key, v)
55 } 56 }
56 57
57 // The waiter is inserted, call the value constructor, store it, and signal the waiter 58 // The waiter is inserted, call the value constructor, store it, and signal the waiter. Use defer in case
58 v := value() 59 // the function panics.
59 once.values.Store(key, v) 60 var v interface{}
60 close(waiter) 61 defer func() {
62 once.values.Store(key, v)
63 close(waiter)
64 }()
65
66 v = value()
61 67
62 return v 68 return v
63} 69}