1
0
mirror of https://github.com/json-iterator/go.git synced 2025-01-20 18:48:32 +02:00

#65 make placeholder thread safe

This commit is contained in:
Tao Wen 2017-06-20 07:39:38 +08:00
parent 839247df05
commit 365d399192

View File

@ -6,6 +6,7 @@ import (
"fmt"
"reflect"
"unsafe"
"time"
)
// Decoder is an internal type registered to cache as needed.
@ -169,11 +170,12 @@ func (encoder *optionalEncoder) isEmpty(ptr unsafe.Pointer) bool {
}
type placeholderEncoder struct {
valueEncoder Encoder
cfg *frozenConfig
cacheKey reflect.Type
}
func (encoder *placeholderEncoder) encode(ptr unsafe.Pointer, stream *Stream) {
encoder.valueEncoder.encode(ptr, stream)
encoder.getRealEncoder().encode(ptr, stream)
}
func (encoder *placeholderEncoder) encodeInterface(val interface{}, stream *Stream) {
@ -181,15 +183,39 @@ func (encoder *placeholderEncoder) encodeInterface(val interface{}, stream *Stre
}
func (encoder *placeholderEncoder) isEmpty(ptr unsafe.Pointer) bool {
return encoder.valueEncoder.isEmpty(ptr)
return encoder.getRealEncoder().isEmpty(ptr)
}
func (encoder *placeholderEncoder) getRealEncoder() Encoder {
for i := 0; i < 30; i++ {
realDecoder := encoder.cfg.getEncoderFromCache(encoder.cacheKey)
_, isPlaceholder := realDecoder.(*placeholderEncoder)
if isPlaceholder {
time.Sleep(time.Second)
} else {
return realDecoder
}
}
panic(fmt.Sprintf("real encoder not found for cache key: %v", encoder.cacheKey))
}
type placeholderDecoder struct {
valueDecoder Decoder
cfg *frozenConfig
cacheKey reflect.Type
}
func (decoder *placeholderDecoder) decode(ptr unsafe.Pointer, iter *Iterator) {
decoder.valueDecoder.decode(ptr, iter)
for i := 0; i < 30; i++ {
realDecoder := decoder.cfg.getDecoderFromCache(decoder.cacheKey)
_, isPlaceholder := realDecoder.(*placeholderDecoder)
if isPlaceholder {
time.Sleep(time.Second)
} else {
realDecoder.decode(ptr, iter)
return
}
}
panic(fmt.Sprintf("real decoder not found for cache key: %v", decoder.cacheKey))
}
// emptyInterface is the header for an interface{} value.
@ -283,10 +309,9 @@ func decoderOfType(cfg *frozenConfig, typ reflect.Type) (Decoder, error) {
if cachedDecoder != nil {
return cachedDecoder, nil
}
placeholder := &placeholderDecoder{}
placeholder := &placeholderDecoder{cfg: cfg, cacheKey: cacheKey}
cfg.addDecoderToCache(cacheKey, placeholder)
newDecoder, err := createDecoderOfType(cfg, typ)
placeholder.valueDecoder = newDecoder
cfg.addDecoderToCache(cacheKey, newDecoder)
return newDecoder, err
}
@ -382,10 +407,9 @@ func encoderOfType(cfg *frozenConfig, typ reflect.Type) (Encoder, error) {
if cachedEncoder != nil {
return cachedEncoder, nil
}
placeholder := &placeholderEncoder{}
placeholder := &placeholderEncoder{cfg: cfg, cacheKey: cacheKey}
cfg.addEncoderToCache(cacheKey, placeholder)
newEncoder, err := createEncoderOfType(cfg, typ)
placeholder.valueEncoder = newEncoder
cfg.addEncoderToCache(cacheKey, newEncoder)
return newEncoder, err
}