You've already forked json-iterator
							
							
				mirror of
				https://github.com/json-iterator/go.git
				synced 2025-10-31 00:07:40 +02:00 
			
		
		
		
	#65 make placeholder thread safe
This commit is contained in:
		| @@ -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 | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user