aboutsummaryrefslogtreecommitdiff
path: root/src/encoding/json/encode.go
diff options
context:
space:
mode:
Diffstat (limited to 'src/encoding/json/encode.go')
-rw-r--r--src/encoding/json/encode.go23
1 files changed, 10 insertions, 13 deletions
diff --git a/src/encoding/json/encode.go b/src/encoding/json/encode.go
index 78d0865b89..1992e7372e 100644
--- a/src/encoding/json/encode.go
+++ b/src/encoding/json/encode.go
@@ -359,25 +359,22 @@ func typeEncoder(t reflect.Type) encoderFunc {
}
// To deal with recursive types, populate the map with an
- // indirect func before we build it. This type waits on the
- // real func (f) to be ready and then calls it. This indirect
- // func is only used for recursive types.
- var (
- wg sync.WaitGroup
- f encoderFunc
- )
- wg.Add(1)
+ // indirect func before we build it. If the type is recursive,
+ // the second lookup for the type will return the indirect func.
+ //
+ // This indirect func is only used for recursive types,
+ // and briefly during racing calls to typeEncoder.
+ indirect := sync.OnceValue(func() encoderFunc {
+ return newTypeEncoder(t, true)
+ })
fi, loaded := encoderCache.LoadOrStore(t, encoderFunc(func(e *encodeState, v reflect.Value, opts encOpts) {
- wg.Wait()
- f(e, v, opts)
+ indirect()(e, v, opts)
}))
if loaded {
return fi.(encoderFunc)
}
- // Compute the real encoder and replace the indirect func with it.
- f = newTypeEncoder(t, true)
- wg.Done()
+ f := indirect()
encoderCache.Store(t, f)
return f
}