Moved RmiFieldCache into better data structure (single-writer-principle variant). code polish
This commit is contained in:
parent
52f5c1688b
commit
428e1fc9c1
|
@ -16,47 +16,19 @@
|
|||
package dorkbox.network.pipeline;
|
||||
|
||||
import dorkbox.network.connection.ConnectionImpl;
|
||||
import dorkbox.network.connection.EndPoint;
|
||||
import dorkbox.network.rmi.CachedMethod;
|
||||
import dorkbox.network.rmi.RMI;
|
||||
import dorkbox.network.rmi.OverriddenMethods;
|
||||
import dorkbox.network.rmi.RemoteObject;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.handler.codec.MessageToMessageDecoder;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
public
|
||||
class LocalRmiDecoder extends MessageToMessageDecoder<Object> {
|
||||
|
||||
private static final Map<Class<?>, Field[]> fieldCache = new ConcurrentHashMap<Class<?>, Field[]>(EndPoint.DEFAULT_THREAD_POOL_SIZE);
|
||||
|
||||
static
|
||||
Field[] getRmiFields(final Class<?> clazz) {
|
||||
// duplicates are OK, because they will contain the same information
|
||||
Field[] rmiFields = fieldCache.get(clazz);
|
||||
if (rmiFields != null) {
|
||||
return rmiFields;
|
||||
}
|
||||
|
||||
final ArrayList<Field> fields = new ArrayList<Field>();
|
||||
|
||||
for (Field field : clazz.getDeclaredFields()) {
|
||||
if (field.getAnnotation(RMI.class) != null) {
|
||||
fields.add(field);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
rmiFields = new Field[fields.size()];
|
||||
fields.toArray(rmiFields);
|
||||
|
||||
fieldCache.put(clazz, rmiFields);
|
||||
return rmiFields;
|
||||
}
|
||||
private static final RmiFieldCache fieldCache = RmiFieldCache.INSTANCE();
|
||||
private static final OverriddenMethods overriddenMethods = OverriddenMethods.INSTANCE();
|
||||
|
||||
public
|
||||
LocalRmiDecoder() {
|
||||
|
@ -79,7 +51,7 @@ class LocalRmiDecoder extends MessageToMessageDecoder<Object> {
|
|||
Object localRmiObject = null;
|
||||
Field field;
|
||||
int registeredId;
|
||||
final Field[] rmiFields = getRmiFields(messageClass);
|
||||
final Field[] rmiFields = fieldCache.get(messageClass);
|
||||
for (int i = 0; i < rmiFields.length; i++) {
|
||||
field = rmiFields[i];
|
||||
registeredId = rmiFieldIds[i];
|
||||
|
@ -94,12 +66,15 @@ class LocalRmiDecoder extends MessageToMessageDecoder<Object> {
|
|||
e.printStackTrace();
|
||||
}
|
||||
|
||||
final Class<?> iface = CachedMethod.overriddenReverseMethods.get(localRmiObject.getClass());
|
||||
if (localRmiObject == null) {
|
||||
throw new RuntimeException("Unable to get RMI interface object for RMI implementation");
|
||||
}
|
||||
|
||||
final Class<?> iface = overriddenMethods.getReverse(localRmiObject.getClass());
|
||||
if (iface == null) {
|
||||
throw new RuntimeException("Unable to get interface for RMI implementation");
|
||||
}
|
||||
|
||||
|
||||
RemoteObject remoteObject = connection.getProxyObject(registeredId, iface);
|
||||
field.set(messageObject, remoteObject);
|
||||
}
|
||||
|
|
|
@ -23,7 +23,6 @@ import io.netty.channel.ChannelHandlerContext;
|
|||
import io.netty.handler.codec.MessageToMessageEncoder;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.WeakHashMap;
|
||||
|
@ -34,31 +33,7 @@ public
|
|||
class LocalRmiEncoder extends MessageToMessageEncoder<Object> {
|
||||
|
||||
private static final Map<Class<?>, Boolean> transformObjectCache = new ConcurrentHashMap<Class<?>, Boolean>(EndPoint.DEFAULT_THREAD_POOL_SIZE);
|
||||
private static final Map<Class<?>, Field[]> fieldCache = new ConcurrentHashMap<Class<?>, Field[]>(EndPoint.DEFAULT_THREAD_POOL_SIZE);
|
||||
|
||||
static
|
||||
Field[] getRmiFields(final Class<?> clazz) {
|
||||
// duplicates are OK, because they will contain the same information
|
||||
Field[] rmiFields = fieldCache.get(clazz);
|
||||
if (rmiFields != null) {
|
||||
return rmiFields;
|
||||
}
|
||||
|
||||
final ArrayList<Field> fields = new ArrayList<Field>();
|
||||
|
||||
for (Field field : clazz.getDeclaredFields()) {
|
||||
if (field.getAnnotation(RMI.class) != null) {
|
||||
fields.add(field);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
rmiFields = new Field[fields.size()];
|
||||
fields.toArray(rmiFields);
|
||||
|
||||
fieldCache.put(clazz, rmiFields);
|
||||
return rmiFields;
|
||||
}
|
||||
private static final RmiFieldCache fieldCache = RmiFieldCache.INSTANCE();
|
||||
|
||||
private final ThreadLocal<Map<Object, Integer>> threadLocal = new ThreadLocal<Map<Object, Integer>>() {
|
||||
@Override
|
||||
|
@ -115,7 +90,7 @@ class LocalRmiEncoder extends MessageToMessageEncoder<Object> {
|
|||
|
||||
private
|
||||
Object replaceFieldObjects(final ConnectionImpl connection, final Object object, final Class<?> implClass) {
|
||||
Field[] rmiFields = getRmiFields(implClass);
|
||||
Field[] rmiFields = fieldCache.get(implClass);
|
||||
int length = rmiFields.length;
|
||||
|
||||
Object rmiObject = null;
|
||||
|
|
58
src/dorkbox/network/pipeline/RmiFieldCache.java
Normal file
58
src/dorkbox/network/pipeline/RmiFieldCache.java
Normal file
|
@ -0,0 +1,58 @@
|
|||
package dorkbox.network.pipeline;
|
||||
|
||||
import com.esotericsoftware.kryo.util.IdentityMap;
|
||||
import dorkbox.network.rmi.RMI;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.ArrayList;
|
||||
import java.util.concurrent.atomic.AtomicReferenceFieldUpdater;
|
||||
|
||||
/**
|
||||
* Uses the "single writer principle" for fast access, but disregards 'single writer', because duplicates are OK
|
||||
*/
|
||||
class RmiFieldCache {
|
||||
private volatile IdentityMap<Class<?>, Field[]> fieldCache = new IdentityMap<Class<?>, Field[]>();
|
||||
|
||||
private static final AtomicReferenceFieldUpdater<RmiFieldCache, IdentityMap> rmiFieldsREF =
|
||||
AtomicReferenceFieldUpdater.newUpdater(RmiFieldCache.class,
|
||||
IdentityMap.class,
|
||||
"fieldCache");
|
||||
|
||||
private static final RmiFieldCache INSTANCE = new RmiFieldCache();
|
||||
public static synchronized RmiFieldCache INSTANCE() {
|
||||
return INSTANCE;
|
||||
}
|
||||
|
||||
private
|
||||
RmiFieldCache() {
|
||||
}
|
||||
|
||||
Field[] get(final Class<?> clazz) {
|
||||
// duplicates are OK, because they will contain the same information, so we DO NOT care about single writers
|
||||
|
||||
//noinspection unchecked
|
||||
final IdentityMap<Class<?>, Field[]> identityMap = rmiFieldsREF.get(this);
|
||||
|
||||
|
||||
Field[] rmiFields = identityMap.get(clazz);
|
||||
if (rmiFields != null) {
|
||||
return rmiFields;
|
||||
}
|
||||
|
||||
final ArrayList<Field> fields = new ArrayList<Field>();
|
||||
|
||||
for (Field field : clazz.getDeclaredFields()) {
|
||||
if (field.getAnnotation(RMI.class) != null) {
|
||||
fields.add(field);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
rmiFields = new Field[fields.size()];
|
||||
fields.toArray(rmiFields);
|
||||
|
||||
// save in cache
|
||||
fieldCache.put(clazz, rmiFields);
|
||||
return rmiFields;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user