Archiviert
13
0

Don't copy inflated buffers - they won't be modified in any case.

Resulted in some pretty ugly factory code.
Dieser Commit ist enthalten in:
Kristian S. Stangeland 2012-12-27 16:28:30 +01:00
Ursprung 20ab2a71ac
Commit 0d34b82d72
3 geänderte Dateien mit 55 neuen und 3 gelöschten Zeilen

Datei anzeigen

@ -43,8 +43,11 @@ import com.comphenix.protocol.reflect.FuzzyReflection;
import com.comphenix.protocol.reflect.ObjectWriter; import com.comphenix.protocol.reflect.ObjectWriter;
import com.comphenix.protocol.reflect.StructureModifier; import com.comphenix.protocol.reflect.StructureModifier;
import com.comphenix.protocol.reflect.cloning.AggregateCloner; import com.comphenix.protocol.reflect.cloning.AggregateCloner;
import com.comphenix.protocol.reflect.cloning.BukkitCloner;
import com.comphenix.protocol.reflect.cloning.Cloner; import com.comphenix.protocol.reflect.cloning.Cloner;
import com.comphenix.protocol.reflect.cloning.CollectionCloner;
import com.comphenix.protocol.reflect.cloning.FieldCloner; import com.comphenix.protocol.reflect.cloning.FieldCloner;
import com.comphenix.protocol.reflect.cloning.ImmutableDetector;
import com.comphenix.protocol.reflect.cloning.AggregateCloner.BuilderParameters; import com.comphenix.protocol.reflect.cloning.AggregateCloner.BuilderParameters;
import com.comphenix.protocol.reflect.instances.DefaultInstances; import com.comphenix.protocol.reflect.instances.DefaultInstances;
import com.comphenix.protocol.utility.MinecraftReflection; import com.comphenix.protocol.utility.MinecraftReflection;
@ -78,7 +81,14 @@ public class PacketContainer implements Serializable {
private static ConcurrentMap<Class<?>, Method> readMethods = Maps.newConcurrentMap(); private static ConcurrentMap<Class<?>, Method> readMethods = Maps.newConcurrentMap();
// Used to clone packets // Used to clone packets
private static final AggregateCloner DEEP_CLONER = AggregateCloner.DEFAULT; private static final AggregateCloner DEEP_CLONER = AggregateCloner.newBuilder().
instanceProvider(DefaultInstances.DEFAULT).
andThen(BukkitCloner.class).
andThen(ImmutableDetector.class).
andThen(CollectionCloner.class).
andThen(getSpecializedDeepClonerFactory()).
build();
private static final AggregateCloner SHALLOW_CLONER = AggregateCloner.newBuilder(). private static final AggregateCloner SHALLOW_CLONER = AggregateCloner.newBuilder().
instanceProvider(DefaultInstances.DEFAULT). instanceProvider(DefaultInstances.DEFAULT).
andThen(new Function<BuilderParameters, Cloner>() { andThen(new Function<BuilderParameters, Cloner>() {
@ -405,6 +415,8 @@ public class PacketContainer implements Serializable {
* <p> * <p>
* This will perform a full copy of the entire object tree, only skipping * This will perform a full copy of the entire object tree, only skipping
* known immutable objects and primitive types. * known immutable objects and primitive types.
* <p>
* Note that the inflated buffers in packet 51 and 56 will be copied directly to save memory.
* *
* @return A deep copy of the current packet. * @return A deep copy of the current packet.
*/ */
@ -413,6 +425,28 @@ public class PacketContainer implements Serializable {
return new PacketContainer(getID(), clonedPacket); return new PacketContainer(getID(), clonedPacket);
} }
// To save space, we'll skip copying the inflated buffers in packet 51 and 56
private static Function<BuilderParameters, Cloner> getSpecializedDeepClonerFactory() {
// Look at what you've made me do Java, look at it!!
return new Function<BuilderParameters, Cloner>() {
@Override
public Cloner apply(@Nullable BuilderParameters param) {
return new FieldCloner(param.getAggregateCloner(), param.getInstanceProvider()) {{
this.writer = new ObjectWriter() {
protected void transformField(StructureModifier<Object> modifierSource,
StructureModifier<Object> modifierDest, int fieldIndex) {
// No need to clone inflated buffers
if (modifierSource.getField(fieldIndex).getName().startsWith("inflatedBuffer"))
modifierDest.write(fieldIndex, modifierSource.read(fieldIndex));
else
defaultTransform(modifierSource, modifierDest, getDefaultCloner(), fieldIndex);
};
};
}};
}
};
}
private void writeObject(ObjectOutputStream output) throws IOException { private void writeObject(ObjectOutputStream output) throws IOException {
// Default serialization // Default serialization
output.defaultWriteObject(); output.defaultWriteObject();

Datei anzeigen

@ -35,6 +35,11 @@ import com.google.common.collect.Lists;
* @author Kristian * @author Kristian
*/ */
public class AggregateCloner implements Cloner { public class AggregateCloner implements Cloner {
/**
* Supplies the cloner factories with necessary parameters.
*
* @author Kristian
*/
public static class BuilderParameters { public static class BuilderParameters {
// Can only be modified by the builder // Can only be modified by the builder
private InstanceProvider instanceProvider; private InstanceProvider instanceProvider;

Datei anzeigen

@ -47,12 +47,25 @@ public class FieldCloner implements Cloner {
@Override @Override
protected void transformField(StructureModifier<Object> modifierSource, protected void transformField(StructureModifier<Object> modifierSource,
StructureModifier<Object> modifierDest, int fieldIndex) { StructureModifier<Object> modifierDest, int fieldIndex) {
Object value = modifierSource.read(fieldIndex); defaultTransform(modifierDest, modifierDest, getDefaultCloner(), fieldIndex);
modifierDest.write(fieldIndex, getDefaultCloner().clone(value));
} }
}; };
} }
/**
* Default implementation of the field transform. Applies a clone operation before a field value is written.
* @param modifierSource - modifier for the original object.
* @param modifierDest - modifier for the new cloned object.
* @param defaultCloner - cloner to use.
* @param fieldIndex - the current field index.
*/
protected void defaultTransform(StructureModifier<Object> modifierSource,
StructureModifier<Object> modifierDest, Cloner defaultCloner, int fieldIndex) {
Object value = modifierSource.read(fieldIndex);
modifierDest.write(fieldIndex, defaultCloner.clone(value));
}
@Override @Override
public boolean canClone(Object source) { public boolean canClone(Object source) {
if (source == null) if (source == null)