Skip to content

Commit

Permalink
Make BlueNBT class threadsafe
Browse files Browse the repository at this point in the history
  • Loading branch information
TBlueF committed Jun 23, 2024
1 parent d1aa42c commit 00f3cb5
Showing 1 changed file with 27 additions and 13 deletions.
40 changes: 27 additions & 13 deletions src/main/java/de/bluecolored/bluenbt/BlueNBT.java
Original file line number Diff line number Diff line change
Expand Up @@ -33,15 +33,16 @@
import java.io.OutputStream;
import java.lang.reflect.Type;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

public class BlueNBT {

private final List<TypeSerializerFactory> serializerFactories = new ArrayList<>();
private final List<TypeDeserializerFactory> deserializerFactories = new ArrayList<>();
private final List<InstanceCreatorFactory> instanceCreatorFactories = new ArrayList<>();
private final Map<TypeToken<?>, TypeSerializer<?>> typeSerializerMap = new HashMap<>();
private final Map<TypeToken<?>, TypeDeserializer<?>> typeDeserializerMap = new HashMap<>();
private final Map<TypeToken<?>, InstanceCreator<?>> instanceCreatorMap = new HashMap<>();
private final Map<TypeToken<?>, TypeSerializer<?>> typeSerializerMap = new ConcurrentHashMap<>();
private final Map<TypeToken<?>, TypeDeserializer<?>> typeDeserializerMap = new ConcurrentHashMap<>();
private final Map<TypeToken<?>, InstanceCreator<?>> instanceCreatorMap = new ConcurrentHashMap<>();

@Getter @Setter
private NamingStrategy namingStrategy = NamingStrategy.FIELD_NAME;
Expand All @@ -55,20 +56,21 @@ public BlueNBT() {
register(MapAdapterFactory.INSTANCE);
}

public void register(TypeAdapterFactory typeAdapterFactory) {
public synchronized void register(TypeAdapterFactory typeAdapterFactory) {
serializerFactories.add(typeAdapterFactory);
deserializerFactories.add(typeAdapterFactory);
typeSerializerMap.clear();
}

public void register(TypeSerializerFactory typeSerializerFactory) {
public synchronized void register(TypeSerializerFactory typeSerializerFactory) {
serializerFactories.add(typeSerializerFactory);
}

public void register(TypeDeserializerFactory typeDeserializerFactory) {
public synchronized void register(TypeDeserializerFactory typeDeserializerFactory) {
deserializerFactories.add(typeDeserializerFactory);
}

public void register(InstanceCreatorFactory instanceCreatorFactory) {
public synchronized void register(InstanceCreatorFactory instanceCreatorFactory) {
instanceCreatorFactories.add(instanceCreatorFactory);
}

Expand Down Expand Up @@ -120,11 +122,15 @@ public <U> Optional<? extends InstanceCreator<U>> create(TypeToken<U> createType
});
}

@SuppressWarnings("unchecked")
public <T> TypeSerializer<T> getTypeSerializer(TypeToken<T> type) {
@SuppressWarnings("unchecked")
TypeSerializer<T> serializer = (TypeSerializer<T>) typeSerializerMap.get(type);
if (serializer != null) return serializer;

synchronized (this) {
serializer = (TypeSerializer<T>) typeSerializerMap.get(type);
if (serializer != null ) return serializer;

if (serializer == null) {
FutureTypeSerializer<T> future = new FutureTypeSerializer<>();
typeSerializerMap.put(type, future); // set future before creation of new serializers to avoid recursive creation

Expand All @@ -144,11 +150,15 @@ public <T> TypeSerializer<T> getTypeSerializer(TypeToken<T> type) {
return serializer;
}

@SuppressWarnings("unchecked")
public <T> TypeDeserializer<T> getTypeDeserializer(TypeToken<T> type) {
@SuppressWarnings("unchecked")
TypeDeserializer<T> deserializer = (TypeDeserializer<T>) typeDeserializerMap.get(type);
if (deserializer != null) return deserializer;

synchronized (this) {
deserializer = (TypeDeserializer<T>) typeDeserializerMap.get(type);
if (deserializer != null) return deserializer;

if (deserializer == null) {
FutureTypeDeserializer<T> future = new FutureTypeDeserializer<>();
typeDeserializerMap.put(type, future); // set future before creation of new deserializers to avoid recursive creation

Expand All @@ -168,11 +178,15 @@ public <T> TypeDeserializer<T> getTypeDeserializer(TypeToken<T> type) {
return deserializer;
}

@SuppressWarnings("unchecked")
public <T> InstanceCreator<T> getInstanceCreator(TypeToken<T> type) {
@SuppressWarnings("unchecked")
InstanceCreator<T> instanceCreator = (InstanceCreator<T>) instanceCreatorMap.get(type);
if (instanceCreator != null) return instanceCreator;

synchronized (this) {
instanceCreator = (InstanceCreator<T>) instanceCreatorMap.get(type);
if (instanceCreator != null) return instanceCreator;

if (instanceCreator == null) {
FutureInstanceCreator<T> future = new FutureInstanceCreator<>();
instanceCreatorMap.put(type, future); // set future before creation of new deserializers to avoid recursive creation

Expand Down

0 comments on commit 00f3cb5

Please sign in to comment.