1
0
mirror of https://github.com/json-iterator/go.git synced 2025-01-23 18:54:21 +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" "fmt"
"reflect" "reflect"
"unsafe" "unsafe"
"time"
) )
// Decoder is an internal type registered to cache as needed. // 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 { type placeholderEncoder struct {
valueEncoder Encoder cfg *frozenConfig
cacheKey reflect.Type
} }
func (encoder *placeholderEncoder) encode(ptr unsafe.Pointer, stream *Stream) { 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) { 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 { 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 { type placeholderDecoder struct {
valueDecoder Decoder cfg *frozenConfig
cacheKey reflect.Type
} }
func (decoder *placeholderDecoder) decode(ptr unsafe.Pointer, iter *Iterator) { 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. // emptyInterface is the header for an interface{} value.
@ -283,10 +309,9 @@ func decoderOfType(cfg *frozenConfig, typ reflect.Type) (Decoder, error) {
if cachedDecoder != nil { if cachedDecoder != nil {
return cachedDecoder, nil return cachedDecoder, nil
} }
placeholder := &placeholderDecoder{} placeholder := &placeholderDecoder{cfg: cfg, cacheKey: cacheKey}
cfg.addDecoderToCache(cacheKey, placeholder) cfg.addDecoderToCache(cacheKey, placeholder)
newDecoder, err := createDecoderOfType(cfg, typ) newDecoder, err := createDecoderOfType(cfg, typ)
placeholder.valueDecoder = newDecoder
cfg.addDecoderToCache(cacheKey, newDecoder) cfg.addDecoderToCache(cacheKey, newDecoder)
return newDecoder, err return newDecoder, err
} }
@ -382,10 +407,9 @@ func encoderOfType(cfg *frozenConfig, typ reflect.Type) (Encoder, error) {
if cachedEncoder != nil { if cachedEncoder != nil {
return cachedEncoder, nil return cachedEncoder, nil
} }
placeholder := &placeholderEncoder{} placeholder := &placeholderEncoder{cfg: cfg, cacheKey: cacheKey}
cfg.addEncoderToCache(cacheKey, placeholder) cfg.addEncoderToCache(cacheKey, placeholder)
newEncoder, err := createEncoderOfType(cfg, typ) newEncoder, err := createEncoderOfType(cfg, typ)
placeholder.valueEncoder = newEncoder
cfg.addEncoderToCache(cacheKey, newEncoder) cfg.addEncoderToCache(cacheKey, newEncoder)
return newEncoder, err return newEncoder, err
} }