Code polish/cleanup
This commit is contained in:
parent
4d5b53fa36
commit
89f47fdd8a
@ -93,7 +93,7 @@ import dorkbox.util.messagebus.error.ErrorHandlingSupport;
|
|||||||
* NOTE: Generic type parameters of messages will not be taken into account, e.g. a List<Long> will
|
* NOTE: Generic type parameters of messages will not be taken into account, e.g. a List<Long> will
|
||||||
* publish dispatched to all message handlers that take an instance of List as their parameter
|
* publish dispatched to all message handlers that take an instance of List as their parameter
|
||||||
*
|
*
|
||||||
* @Author bennidi
|
* @author bennidi
|
||||||
* Date: 2/8/12
|
* Date: 2/8/12
|
||||||
* @author dorkbox, llc
|
* @author dorkbox, llc
|
||||||
* Date: 2/2/15
|
* Date: 2/2/15
|
||||||
|
@ -43,7 +43,7 @@ package dorkbox.util.messagebus;
|
|||||||
* Listeners can be subscribed and unsubscribed using the corresponding methods. When a listener is subscribed its
|
* Listeners can be subscribed and unsubscribed using the corresponding methods. When a listener is subscribed its
|
||||||
* handlers will be registered and start to receive matching message publications.
|
* handlers will be registered and start to receive matching message publications.
|
||||||
*
|
*
|
||||||
* @Author bennidi
|
* @author bennidi
|
||||||
* @author dorkbox, llc
|
* @author dorkbox, llc
|
||||||
* Date: 2/2/15
|
* Date: 2/2/15
|
||||||
*/
|
*/
|
||||||
|
@ -56,7 +56,8 @@ public class ClassTree<KEY> {
|
|||||||
|
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public static <KEY> IdentityMap<KEY, ClassTree<KEY>> cast(Object o) {
|
private static
|
||||||
|
<KEY> IdentityMap<KEY, ClassTree<KEY>> cast(Object o) {
|
||||||
return (IdentityMap<KEY, ClassTree<KEY>>) o;
|
return (IdentityMap<KEY, ClassTree<KEY>>) o;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -109,28 +110,11 @@ public class ClassTree<KEY> {
|
|||||||
return getOrCreateValue(leaf);
|
return getOrCreateValue(leaf);
|
||||||
}
|
}
|
||||||
|
|
||||||
public final
|
|
||||||
MultiClass get(KEY... keys) {
|
|
||||||
if (keys == null) {
|
|
||||||
throw new NullPointerException("keys");
|
|
||||||
}
|
|
||||||
|
|
||||||
int length = keys.length;
|
|
||||||
|
|
||||||
// have to put value into our children
|
|
||||||
ClassTree<KEY> leaf = getOrCreateLeaf(keys[0]);
|
|
||||||
for (int i=1;i<length;i++) {
|
|
||||||
leaf = leaf.getOrCreateLeaf(keys[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
return getOrCreateValue(leaf);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* creates a child (if necessary) in an atomic way. The tree returned will either be the current one, or a new one.
|
* creates a child (if necessary) in an atomic way. The tree returned will either be the current one, or a new one.
|
||||||
*
|
*
|
||||||
* @param key the key for the new child
|
* @param key the key for the new child
|
||||||
* @return
|
* @return the existing (or new) leaf
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
private
|
private
|
||||||
|
@ -17,7 +17,7 @@ package dorkbox.util.messagebus.common;
|
|||||||
|
|
||||||
// not thread-safe! must be synchronized in enclosing context
|
// not thread-safe! must be synchronized in enclosing context
|
||||||
public class Entry {
|
public class Entry {
|
||||||
private Object value;
|
private final Object value;
|
||||||
private Entry next;
|
private Entry next;
|
||||||
private Entry prev;
|
private Entry prev;
|
||||||
|
|
||||||
|
@ -64,6 +64,9 @@ import java.util.ArrayList;
|
|||||||
*/
|
*/
|
||||||
public
|
public
|
||||||
class MessageHandler {
|
class MessageHandler {
|
||||||
|
|
||||||
|
private static final MessageHandler[] EMPTY_MESSAGEHANDLERS = new MessageHandler[0];
|
||||||
|
|
||||||
// publish all listeners defined by the given class (includes listeners defined in super classes)
|
// publish all listeners defined by the given class (includes listeners defined in super classes)
|
||||||
public static
|
public static
|
||||||
MessageHandler[] get(final Class<?> messageClass) {
|
MessageHandler[] get(final Class<?> messageClass) {
|
||||||
@ -99,7 +102,7 @@ class MessageHandler {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return finalMethods.toArray(new MessageHandler[0]);
|
return finalMethods.toArray(EMPTY_MESSAGEHANDLERS);
|
||||||
}
|
}
|
||||||
|
|
||||||
private final Method method;
|
private final Method method;
|
||||||
|
@ -101,7 +101,7 @@ class NamedThreadFactory implements ThreadFactory {
|
|||||||
return newThread(stringBuilder.toString(), r);
|
return newThread(stringBuilder.toString(), r);
|
||||||
}
|
}
|
||||||
|
|
||||||
public
|
private
|
||||||
Thread newThread(String name, Runnable r) {
|
Thread newThread(String name, Runnable r) {
|
||||||
// stack size is arbitrary based on JVM implementation. Default is 0
|
// stack size is arbitrary based on JVM implementation. Default is 0
|
||||||
// 8k is the size of the android stack. Depending on the version of android, this can either change, or will always be 8k
|
// 8k is the size of the android stack. Depending on the version of android, this can either change, or will always be 8k
|
||||||
|
@ -23,10 +23,10 @@
|
|||||||
package dorkbox.util.messagebus.error;
|
package dorkbox.util.messagebus.error;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Publication error handlers are provided with a publication error every time an
|
* Publication error handlers are provided with a publication error every time an error occurs during message publication.
|
||||||
* error occurs during message publication.
|
* <p/>
|
||||||
* A handler might fail with an exception, not be accessible because of the presence
|
* A handler might fail with an exception, not be accessible because of the presence of a security manager or other reasons might
|
||||||
* of a security manager or other reasons might lead to failures during the message publication process.
|
* lead to failures during the message publication process.
|
||||||
* <p/>
|
* <p/>
|
||||||
*
|
*
|
||||||
* @author bennidi
|
* @author bennidi
|
||||||
@ -46,14 +46,13 @@ interface IPublicationErrorHandler {
|
|||||||
* Handle the given publication error.
|
* Handle the given publication error.
|
||||||
*
|
*
|
||||||
* @param error The PublicationError to handle.
|
* @param error The PublicationError to handle.
|
||||||
* @param listenerClass
|
* @param listenerClass The class that caused the error to occur
|
||||||
*/
|
*/
|
||||||
void handleError(String error, final Class<?> listenerClass);
|
void handleError(String error, final Class<?> listenerClass);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The default error handler will simply log to standard out and
|
* The default error handler will simply log to standard out and print the stack trace if available.
|
||||||
* print the stack trace if available.
|
|
||||||
*/
|
*/
|
||||||
final
|
final
|
||||||
class ConsoleLogger implements IPublicationErrorHandler {
|
class ConsoleLogger implements IPublicationErrorHandler {
|
||||||
|
@ -39,7 +39,7 @@ import java.util.concurrent.atomic.AtomicReferenceFieldUpdater;
|
|||||||
public abstract
|
public abstract
|
||||||
class Subscription {
|
class Subscription {
|
||||||
private static final AtomicInteger ID_COUNTER = new AtomicInteger();
|
private static final AtomicInteger ID_COUNTER = new AtomicInteger();
|
||||||
public final int ID = ID_COUNTER.getAndIncrement();
|
private final int ID = ID_COUNTER.getAndIncrement();
|
||||||
|
|
||||||
|
|
||||||
// this is the listener class that created this subscription
|
// this is the listener class that created this subscription
|
||||||
@ -58,7 +58,8 @@ class Subscription {
|
|||||||
private final IdentityMap<Object, Entry> entries; // maintain a map of entries for FAST lookup during unsubscribe.
|
private final IdentityMap<Object, Entry> entries; // maintain a map of entries for FAST lookup during unsubscribe.
|
||||||
|
|
||||||
// this is still inside the single-writer, and can use the same techniques as subscription manager (for thread safe publication)
|
// this is still inside the single-writer, and can use the same techniques as subscription manager (for thread safe publication)
|
||||||
public volatile Entry head; // reference to the first element
|
// accessed from within SYNCHRONIZE
|
||||||
|
private Entry head; // reference to the first element
|
||||||
|
|
||||||
protected
|
protected
|
||||||
Subscription(final Class<?> listenerClass, final MessageHandler handler) {
|
Subscription(final Class<?> listenerClass, final MessageHandler handler) {
|
||||||
@ -90,6 +91,7 @@ class Subscription {
|
|||||||
public final
|
public final
|
||||||
void subscribe(final Object listener) {
|
void subscribe(final Object listener) {
|
||||||
// single writer principle!
|
// single writer principle!
|
||||||
|
// called from within SYNCHRONIZE
|
||||||
Entry head = headREF.get(this);
|
Entry head = headREF.get(this);
|
||||||
|
|
||||||
if (!entries.containsKey(listener)) {
|
if (!entries.containsKey(listener)) {
|
||||||
@ -100,18 +102,13 @@ class Subscription {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @return TRUE if the element was removed
|
|
||||||
*/
|
|
||||||
public final
|
public final
|
||||||
boolean unsubscribe(final Object listener) {
|
void unsubscribe(final Object listener) {
|
||||||
Entry entry = entries.get(listener);
|
Entry entry = entries.get(listener);
|
||||||
if (entry == null || entry.getValue() == null) {
|
|
||||||
// fast exit
|
if (entry != null && entry.getValue() != null) {
|
||||||
return false;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// single writer principle!
|
// single writer principle!
|
||||||
|
// called from within SYNCHRONIZE
|
||||||
Entry head = headREF.get(this);
|
Entry head = headREF.get(this);
|
||||||
|
|
||||||
if (entry != head) {
|
if (entry != head) {
|
||||||
@ -125,7 +122,6 @@ class Subscription {
|
|||||||
|
|
||||||
this.entries.remove(listener);
|
this.entries.remove(listener);
|
||||||
headREF.lazySet(this, head);
|
headREF.lazySet(this, head);
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -43,7 +43,7 @@ import java.util.concurrent.atomic.AtomicReferenceFieldUpdater;
|
|||||||
public final
|
public final
|
||||||
class SubscriptionManager {
|
class SubscriptionManager {
|
||||||
public static final float LOAD_FACTOR = 0.8F;
|
public static final float LOAD_FACTOR = 0.8F;
|
||||||
public static final Subscription[] EMPTY_SUBS = new Subscription[0];
|
private static final Subscription[] EMPTY_SUBS = new Subscription[0];
|
||||||
|
|
||||||
// controls if we use java reflection or ASM to access methods during publication
|
// controls if we use java reflection or ASM to access methods during publication
|
||||||
private final SubMaker subMaker;
|
private final SubMaker subMaker;
|
||||||
@ -112,7 +112,7 @@ class SubscriptionManager {
|
|||||||
this.subMaker = new SubMakerReflection();
|
this.subMaker = new SubMakerReflection();
|
||||||
}
|
}
|
||||||
|
|
||||||
classUtils = new ClassUtils(SubscriptionManager.LOAD_FACTOR);
|
classUtils = new ClassUtils();
|
||||||
classTree = new ClassTree<Class<?>>();
|
classTree = new ClassTree<Class<?>>();
|
||||||
|
|
||||||
|
|
||||||
@ -321,25 +321,7 @@ class SubscriptionManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
default: {
|
default: {
|
||||||
multiClass = classTree.get(messageHandlerTypes);
|
throw new RuntimeException("Unsupported number of parameters during subscribe. Acceptable max is 3");
|
||||||
|
|
||||||
// makes this subscription visible for publication
|
|
||||||
final Subscription[] newSubs;
|
|
||||||
Subscription[] currentSubs = multiSubs.get(multiClass);
|
|
||||||
|
|
||||||
if (currentSubs != null) {
|
|
||||||
final int currentLength = currentSubs.length;
|
|
||||||
|
|
||||||
// add the new subscription to the array
|
|
||||||
newSubs = Arrays.copyOf(currentSubs, currentLength + 1, Subscription[].class);
|
|
||||||
newSubs[currentLength] = subscription;
|
|
||||||
} else {
|
|
||||||
newSubs = new Subscription[1];
|
|
||||||
newSubs[0] = subscription;
|
|
||||||
}
|
|
||||||
|
|
||||||
multiSubs.put(multiClass, newSubs);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -54,7 +54,7 @@ import com.esotericsoftware.reflectasm.MethodAccess;
|
|||||||
* @author dorkbox, llc
|
* @author dorkbox, llc
|
||||||
* Date: 2/2/15
|
* Date: 2/2/15
|
||||||
*/
|
*/
|
||||||
public interface AsmInvocation {
|
interface AsmInvocation {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Invoke the message delivery logic of this handler
|
* Invoke the message delivery logic of this handler
|
||||||
|
@ -50,7 +50,7 @@ import com.esotericsoftware.reflectasm.MethodAccess;
|
|||||||
public
|
public
|
||||||
class AsmSynchronizedInvocation implements AsmInvocation {
|
class AsmSynchronizedInvocation implements AsmInvocation {
|
||||||
|
|
||||||
private AsmInvocation delegate;
|
private final AsmInvocation delegate;
|
||||||
|
|
||||||
public
|
public
|
||||||
AsmSynchronizedInvocation(AsmInvocation delegate) {
|
AsmSynchronizedInvocation(AsmInvocation delegate) {
|
||||||
|
@ -86,9 +86,6 @@ class SubscriptionAsm extends Subscription {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return true if messages were published
|
|
||||||
*/
|
|
||||||
public
|
public
|
||||||
void publish(final Object message) throws Throwable {
|
void publish(final Object message) throws Throwable {
|
||||||
final MethodAccess handler = this.handlerAccess;
|
final MethodAccess handler = this.handlerAccess;
|
||||||
@ -105,9 +102,6 @@ class SubscriptionAsm extends Subscription {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @return true if messages were published
|
|
||||||
*/
|
|
||||||
public
|
public
|
||||||
void publish(final Object message1, final Object message2) throws Throwable {
|
void publish(final Object message1, final Object message2) throws Throwable {
|
||||||
final MethodAccess handler = this.handlerAccess;
|
final MethodAccess handler = this.handlerAccess;
|
||||||
@ -124,9 +118,6 @@ class SubscriptionAsm extends Subscription {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @return true if messages were published
|
|
||||||
*/
|
|
||||||
public
|
public
|
||||||
void publish(final Object message1, final Object message2, final Object message3) throws Throwable {
|
void publish(final Object message1, final Object message2, final Object message3) throws Throwable {
|
||||||
final MethodAccess handler = this.handlerAccess;
|
final MethodAccess handler = this.handlerAccess;
|
||||||
|
@ -54,7 +54,7 @@ import java.lang.reflect.Method;
|
|||||||
* @author dorkbox, llc
|
* @author dorkbox, llc
|
||||||
* Date: 2/2/15
|
* Date: 2/2/15
|
||||||
*/
|
*/
|
||||||
public interface ReflectionInvocation {
|
interface ReflectionInvocation {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Invoke the message delivery logic of this handler
|
* Invoke the message delivery logic of this handler
|
||||||
|
@ -50,7 +50,7 @@ import java.lang.reflect.Method;
|
|||||||
public
|
public
|
||||||
class ReflectionSynchronizedInvocation implements ReflectionInvocation {
|
class ReflectionSynchronizedInvocation implements ReflectionInvocation {
|
||||||
|
|
||||||
private ReflectionInvocation delegate;
|
private final ReflectionInvocation delegate;
|
||||||
|
|
||||||
public
|
public
|
||||||
ReflectionSynchronizedInvocation(ReflectionInvocation delegate) {
|
ReflectionSynchronizedInvocation(ReflectionInvocation delegate) {
|
||||||
|
@ -79,9 +79,6 @@ class SubscriptionReflection extends Subscription {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return true if messages were published
|
|
||||||
*/
|
|
||||||
public
|
public
|
||||||
void publish(final Object message) throws Throwable {
|
void publish(final Object message) throws Throwable {
|
||||||
final Method method = this.method;
|
final Method method = this.method;
|
||||||
@ -97,9 +94,6 @@ class SubscriptionReflection extends Subscription {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @return true if messages were published
|
|
||||||
*/
|
|
||||||
public
|
public
|
||||||
void publish(final Object message1, final Object message2) throws Throwable {
|
void publish(final Object message1, final Object message2) throws Throwable {
|
||||||
final Method method = this.method;
|
final Method method = this.method;
|
||||||
@ -115,9 +109,6 @@ class SubscriptionReflection extends Subscription {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @return true if messages were published
|
|
||||||
*/
|
|
||||||
public
|
public
|
||||||
void publish(final Object message1, final Object message2, final Object message3) throws Throwable {
|
void publish(final Object message1, final Object message2, final Object message3) throws Throwable {
|
||||||
final Method method = this.method;
|
final Method method = this.method;
|
||||||
|
@ -52,7 +52,7 @@ class AsyncABQ implements Synchrony {
|
|||||||
|
|
||||||
// each thread will run forever and process incoming message publication requests
|
// each thread will run forever and process incoming message publication requests
|
||||||
Runnable runnable = new Runnable() {
|
Runnable runnable = new Runnable() {
|
||||||
@SuppressWarnings("ConstantConditions")
|
@SuppressWarnings({"ConstantConditions", "UnnecessaryLocalVariable"})
|
||||||
@Override
|
@Override
|
||||||
public
|
public
|
||||||
void run() {
|
void run() {
|
||||||
|
@ -62,7 +62,7 @@ class AsyncABQ_noGc implements Synchrony {
|
|||||||
|
|
||||||
// each thread will run forever and process incoming message publication requests
|
// each thread will run forever and process incoming message publication requests
|
||||||
Runnable runnable = new Runnable() {
|
Runnable runnable = new Runnable() {
|
||||||
@SuppressWarnings("ConstantConditions")
|
@SuppressWarnings({"ConstantConditions", "UnnecessaryLocalVariable"})
|
||||||
@Override
|
@Override
|
||||||
public
|
public
|
||||||
void run() {
|
void run() {
|
||||||
|
@ -35,10 +35,10 @@ import java.util.concurrent.locks.LockSupport;
|
|||||||
public final
|
public final
|
||||||
class AsyncDisruptor implements Synchrony {
|
class AsyncDisruptor implements Synchrony {
|
||||||
|
|
||||||
private WorkProcessor[] workProcessors;
|
private final WorkProcessor[] workProcessors;
|
||||||
private MessageHandler[] handlers;
|
private final MessageHandler[] handlers;
|
||||||
private RingBuffer<MessageHolder> ringBuffer;
|
private final RingBuffer<MessageHolder> ringBuffer;
|
||||||
private Sequence workSequence;
|
private final Sequence workSequence;
|
||||||
|
|
||||||
public
|
public
|
||||||
AsyncDisruptor(final int numberOfThreads, final ErrorHandlingSupport errorHandler, final Synchrony syncPublication) {
|
AsyncDisruptor(final int numberOfThreads, final ErrorHandlingSupport errorHandler, final Synchrony syncPublication) {
|
||||||
|
@ -32,29 +32,4 @@ class MessageHolder {
|
|||||||
|
|
||||||
public
|
public
|
||||||
MessageHolder() {}
|
MessageHolder() {}
|
||||||
|
|
||||||
public
|
|
||||||
MessageHolder(Subscription[] subscriptions, Object message1) {
|
|
||||||
this.subscriptions = subscriptions;
|
|
||||||
this.message1 = message1;
|
|
||||||
}
|
|
||||||
|
|
||||||
public
|
|
||||||
MessageHolder(Subscription[] subscriptions, Object message1, Object message2) {
|
|
||||||
type = MessageType.TWO;
|
|
||||||
|
|
||||||
this.subscriptions = subscriptions;
|
|
||||||
this.message1 = message1;
|
|
||||||
this.message2 = message2;
|
|
||||||
}
|
|
||||||
|
|
||||||
public
|
|
||||||
MessageHolder(Subscription[] subscriptions, Object message1, Object message2, Object message3) {
|
|
||||||
type = MessageType.THREE;
|
|
||||||
|
|
||||||
this.subscriptions = subscriptions;
|
|
||||||
this.message1 = message1;
|
|
||||||
this.message2 = message2;
|
|
||||||
this.message3 = message3;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
package dorkbox.util.messagebus.utils;
|
package dorkbox.util.messagebus.utils;
|
||||||
|
|
||||||
import com.esotericsoftware.kryo.util.IdentityMap;
|
import com.esotericsoftware.kryo.util.IdentityMap;
|
||||||
|
import dorkbox.util.messagebus.subscription.SubscriptionManager;
|
||||||
|
|
||||||
import java.lang.reflect.Array;
|
import java.lang.reflect.Array;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
@ -43,9 +44,9 @@ class ClassUtils {
|
|||||||
* principle" for storing data, EVEN THOUGH it's not accessed by a single writer. This DOES NOT MATTER because duplicates DO NOT matter
|
* principle" for storing data, EVEN THOUGH it's not accessed by a single writer. This DOES NOT MATTER because duplicates DO NOT matter
|
||||||
*/
|
*/
|
||||||
public
|
public
|
||||||
ClassUtils(final float loadFactor) {
|
ClassUtils() {
|
||||||
this.arrayCache = new IdentityMap<Class<?>, Class<?>>(32, loadFactor);
|
this.arrayCache = new IdentityMap<Class<?>, Class<?>>(32, SubscriptionManager.LOAD_FACTOR);
|
||||||
this.superClassesCache = new IdentityMap<Class<?>, Class<?>[]>(32, loadFactor);
|
this.superClassesCache = new IdentityMap<Class<?>, Class<?>[]>(32, SubscriptionManager.LOAD_FACTOR);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -58,7 +59,7 @@ class ClassUtils {
|
|||||||
public
|
public
|
||||||
Class<?>[] getSuperClasses(final Class<?> clazz) {
|
Class<?>[] getSuperClasses(final Class<?> clazz) {
|
||||||
// access a snapshot of the subscriptions (single-writer-principle)
|
// access a snapshot of the subscriptions (single-writer-principle)
|
||||||
final IdentityMap<Class<?>, Class<?>[]> cache = superClassesREF.get(this);
|
final IdentityMap<Class<?>, Class<?>[]> cache = cast(superClassesREF.get(this));
|
||||||
|
|
||||||
Class<?>[] classes = cache.get(clazz);
|
Class<?>[] classes = cache.get(clazz);
|
||||||
|
|
||||||
@ -115,7 +116,7 @@ class ClassUtils {
|
|||||||
public
|
public
|
||||||
Class<?> getArrayClass(final Class<?> c) {
|
Class<?> getArrayClass(final Class<?> c) {
|
||||||
// access a snapshot of the subscriptions (single-writer-principle)
|
// access a snapshot of the subscriptions (single-writer-principle)
|
||||||
final IdentityMap<Class<?>, Class<?>> cache = arrayREF.get(this);
|
final IdentityMap<Class<?>, Class<?>> cache = cast(arrayREF.get(this));
|
||||||
|
|
||||||
Class<?> clazz = cache.get(c);
|
Class<?> clazz = cache.get(c);
|
||||||
|
|
||||||
@ -141,4 +142,10 @@ class ClassUtils {
|
|||||||
this.arrayCache.clear();
|
this.arrayCache.clear();
|
||||||
this.superClassesCache.clear();
|
this.superClassesCache.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
private static
|
||||||
|
<T> T cast(Object obj) {
|
||||||
|
return (T) obj;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -56,6 +56,9 @@ import java.util.Collection;
|
|||||||
public final
|
public final
|
||||||
class ReflectionUtils {
|
class ReflectionUtils {
|
||||||
|
|
||||||
|
private static final Method[] EMPTY_METHODS = new Method[0];
|
||||||
|
private static final Class<?>[] EMPTY_CLASSES = new Class<?>[0];
|
||||||
|
|
||||||
private
|
private
|
||||||
ReflectionUtils() {
|
ReflectionUtils() {
|
||||||
}
|
}
|
||||||
@ -65,7 +68,7 @@ class ReflectionUtils {
|
|||||||
ArrayList<Method> methods = new ArrayList<Method>();
|
ArrayList<Method> methods = new ArrayList<Method>();
|
||||||
|
|
||||||
getMethods(target, methods);
|
getMethods(target, methods);
|
||||||
return methods.toArray(new Method[0]);
|
return methods.toArray(EMPTY_METHODS);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static
|
private static
|
||||||
@ -111,7 +114,7 @@ class ReflectionUtils {
|
|||||||
* @return A set of classes, each representing a super type of the root class
|
* @return A set of classes, each representing a super type of the root class
|
||||||
*/
|
*/
|
||||||
public static
|
public static
|
||||||
Class<?>[] getSuperTypes2(Class<?> from) {
|
Class<?>[] getSuperTypes(Class<?> from) {
|
||||||
ArrayList<Class<?>> superclasses = new ArrayList<Class<?>>();
|
ArrayList<Class<?>> superclasses = new ArrayList<Class<?>>();
|
||||||
|
|
||||||
collectInterfaces(from, superclasses);
|
collectInterfaces(from, superclasses);
|
||||||
@ -122,25 +125,10 @@ class ReflectionUtils {
|
|||||||
collectInterfaces(from, superclasses);
|
collectInterfaces(from, superclasses);
|
||||||
}
|
}
|
||||||
|
|
||||||
return superclasses.toArray(new Class<?>[0]);
|
return superclasses.toArray(EMPTY_CLASSES);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Class[] getSuperTypes(Class from) {
|
private static
|
||||||
ArrayList<Class<?>> superclasses = new ArrayList<Class<?>>();
|
|
||||||
|
|
||||||
collectInterfaces( from, superclasses );
|
|
||||||
while ( !from.equals( Object.class ) && !from.isInterface() ) {
|
|
||||||
superclasses.add( from.getSuperclass() );
|
|
||||||
from = from.getSuperclass();
|
|
||||||
collectInterfaces( from, superclasses );
|
|
||||||
}
|
|
||||||
|
|
||||||
return superclasses.toArray(new Class[0]);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public static
|
|
||||||
void collectInterfaces(Class<?> from, Collection<Class<?>> accumulator) {
|
void collectInterfaces(Class<?> from, Collection<Class<?>> accumulator) {
|
||||||
for (Class<?> intface : from.getInterfaces()) {
|
for (Class<?> intface : from.getInterfaces()) {
|
||||||
accumulator.add(intface);
|
accumulator.add(intface);
|
||||||
@ -193,8 +181,7 @@ class ReflectionUtils {
|
|||||||
|
|
||||||
public static
|
public static
|
||||||
<A extends Annotation> A getAnnotation(AnnotatedElement from, Class<A> annotationType) {
|
<A extends Annotation> A getAnnotation(AnnotatedElement from, Class<A> annotationType) {
|
||||||
A annotation = getAnnotation(from, annotationType, new IdentityMap<AnnotatedElement, Boolean>());
|
return getAnnotation(from, annotationType, new IdentityMap<AnnotatedElement, Boolean>());
|
||||||
return annotation;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
|
@ -32,8 +32,6 @@ public class MultiTreeTest extends AssertSupport {
|
|||||||
final MultiClass d = tree.get(Object.class, Object.class);
|
final MultiClass d = tree.get(Object.class, Object.class);
|
||||||
final MultiClass e = tree.get(String.class, String.class, String.class);
|
final MultiClass e = tree.get(String.class, String.class, String.class);
|
||||||
|
|
||||||
final MultiClass f = tree.get(String.class, String.class, String.class, String.class);
|
|
||||||
final MultiClass g = tree.get(Object.class, Object.class, String.class, Integer.class, Float.class);
|
|
||||||
|
|
||||||
// we never can remove elements, unless we CLEAR the entire thing (usually at shutdown)
|
// we never can remove elements, unless we CLEAR the entire thing (usually at shutdown)
|
||||||
assertNotNull(a);
|
assertNotNull(a);
|
||||||
@ -41,7 +39,5 @@ public class MultiTreeTest extends AssertSupport {
|
|||||||
assertNotNull(c);
|
assertNotNull(c);
|
||||||
assertNotNull(d);
|
assertNotNull(d);
|
||||||
assertNotNull(e);
|
assertNotNull(e);
|
||||||
assertNotNull(f);
|
|
||||||
assertNotNull(g);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user