Code polish/cleanup

This commit is contained in:
nathan 2016-02-07 00:10:42 +01:00
parent 4d5b53fa36
commit 89f47fdd8a
22 changed files with 58 additions and 147 deletions

View File

@ -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
* publish dispatched to all message handlers that take an instance of List as their parameter
*
* @Author bennidi
* @author bennidi
* Date: 2/8/12
* @author dorkbox, llc
* Date: 2/2/15

View File

@ -43,7 +43,7 @@ package dorkbox.util.messagebus;
* 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.
*
* @Author bennidi
* @author bennidi
* @author dorkbox, llc
* Date: 2/2/15
*/

View File

@ -56,7 +56,8 @@ public class ClassTree<KEY> {
@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;
}
@ -109,28 +110,11 @@ public class ClassTree<KEY> {
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.
*
* @param key the key for the new child
* @return
* @return the existing (or new) leaf
*/
@SuppressWarnings("unchecked")
private

View File

@ -17,7 +17,7 @@ package dorkbox.util.messagebus.common;
// not thread-safe! must be synchronized in enclosing context
public class Entry {
private Object value;
private final Object value;
private Entry next;
private Entry prev;

View File

@ -64,6 +64,9 @@ import java.util.ArrayList;
*/
public
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)
public static
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;

View File

@ -101,7 +101,7 @@ class NamedThreadFactory implements ThreadFactory {
return newThread(stringBuilder.toString(), r);
}
public
private
Thread newThread(String name, Runnable r) {
// 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

View File

@ -23,10 +23,10 @@
package dorkbox.util.messagebus.error;
/**
* Publication error handlers are provided with a publication error every time an
* error occurs during message publication.
* A handler might fail with an exception, not be accessible because of the presence
* of a security manager or other reasons might lead to failures during the message publication process.
* Publication error handlers are provided with a publication error every time an error occurs during message publication.
* <p/>
* A handler might fail with an exception, not be accessible because of the presence of a security manager or other reasons might
* lead to failures during the message publication process.
* <p/>
*
* @author bennidi
@ -46,14 +46,13 @@ interface IPublicationErrorHandler {
* Handle the given publication error.
*
* @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);
/**
* The default error handler will simply log to standard out and
* print the stack trace if available.
* The default error handler will simply log to standard out and print the stack trace if available.
*/
final
class ConsoleLogger implements IPublicationErrorHandler {

View File

@ -39,7 +39,7 @@ import java.util.concurrent.atomic.AtomicReferenceFieldUpdater;
public abstract
class Subscription {
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
@ -58,7 +58,8 @@ class Subscription {
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)
public volatile Entry head; // reference to the first element
// accessed from within SYNCHRONIZE
private Entry head; // reference to the first element
protected
Subscription(final Class<?> listenerClass, final MessageHandler handler) {
@ -90,6 +91,7 @@ class Subscription {
public final
void subscribe(final Object listener) {
// single writer principle!
// called from within SYNCHRONIZE
Entry head = headREF.get(this);
if (!entries.containsKey(listener)) {
@ -100,18 +102,13 @@ class Subscription {
}
}
/**
* @return TRUE if the element was removed
*/
public final
boolean unsubscribe(final Object listener) {
void unsubscribe(final Object listener) {
Entry entry = entries.get(listener);
if (entry == null || entry.getValue() == null) {
// fast exit
return false;
}
else {
if (entry != null && entry.getValue() != null) {
// single writer principle!
// called from within SYNCHRONIZE
Entry head = headREF.get(this);
if (entry != head) {
@ -125,7 +122,6 @@ class Subscription {
this.entries.remove(listener);
headREF.lazySet(this, head);
return true;
}
}

View File

@ -43,7 +43,7 @@ import java.util.concurrent.atomic.AtomicReferenceFieldUpdater;
public final
class SubscriptionManager {
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
private final SubMaker subMaker;
@ -112,7 +112,7 @@ class SubscriptionManager {
this.subMaker = new SubMakerReflection();
}
classUtils = new ClassUtils(SubscriptionManager.LOAD_FACTOR);
classUtils = new ClassUtils();
classTree = new ClassTree<Class<?>>();
@ -321,25 +321,7 @@ class SubscriptionManager {
}
default: {
multiClass = classTree.get(messageHandlerTypes);
// 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;
throw new RuntimeException("Unsupported number of parameters during subscribe. Acceptable max is 3");
}
}
}

View File

@ -54,7 +54,7 @@ import com.esotericsoftware.reflectasm.MethodAccess;
* @author dorkbox, llc
* Date: 2/2/15
*/
public interface AsmInvocation {
interface AsmInvocation {
/**
* Invoke the message delivery logic of this handler

View File

@ -50,7 +50,7 @@ import com.esotericsoftware.reflectasm.MethodAccess;
public
class AsmSynchronizedInvocation implements AsmInvocation {
private AsmInvocation delegate;
private final AsmInvocation delegate;
public
AsmSynchronizedInvocation(AsmInvocation delegate) {

View File

@ -86,9 +86,6 @@ class SubscriptionAsm extends Subscription {
}
/**
* @return true if messages were published
*/
public
void publish(final Object message) throws Throwable {
final MethodAccess handler = this.handlerAccess;
@ -105,9 +102,6 @@ class SubscriptionAsm extends Subscription {
}
}
/**
* @return true if messages were published
*/
public
void publish(final Object message1, final Object message2) throws Throwable {
final MethodAccess handler = this.handlerAccess;
@ -124,9 +118,6 @@ class SubscriptionAsm extends Subscription {
}
}
/**
* @return true if messages were published
*/
public
void publish(final Object message1, final Object message2, final Object message3) throws Throwable {
final MethodAccess handler = this.handlerAccess;

View File

@ -54,7 +54,7 @@ import java.lang.reflect.Method;
* @author dorkbox, llc
* Date: 2/2/15
*/
public interface ReflectionInvocation {
interface ReflectionInvocation {
/**
* Invoke the message delivery logic of this handler

View File

@ -50,7 +50,7 @@ import java.lang.reflect.Method;
public
class ReflectionSynchronizedInvocation implements ReflectionInvocation {
private ReflectionInvocation delegate;
private final ReflectionInvocation delegate;
public
ReflectionSynchronizedInvocation(ReflectionInvocation delegate) {

View File

@ -79,9 +79,6 @@ class SubscriptionReflection extends Subscription {
}
/**
* @return true if messages were published
*/
public
void publish(final Object message) throws Throwable {
final Method method = this.method;
@ -97,9 +94,6 @@ class SubscriptionReflection extends Subscription {
}
}
/**
* @return true if messages were published
*/
public
void publish(final Object message1, final Object message2) throws Throwable {
final Method method = this.method;
@ -115,9 +109,6 @@ class SubscriptionReflection extends Subscription {
}
}
/**
* @return true if messages were published
*/
public
void publish(final Object message1, final Object message2, final Object message3) throws Throwable {
final Method method = this.method;

View File

@ -52,7 +52,7 @@ class AsyncABQ implements Synchrony {
// each thread will run forever and process incoming message publication requests
Runnable runnable = new Runnable() {
@SuppressWarnings("ConstantConditions")
@SuppressWarnings({"ConstantConditions", "UnnecessaryLocalVariable"})
@Override
public
void run() {

View File

@ -62,7 +62,7 @@ class AsyncABQ_noGc implements Synchrony {
// each thread will run forever and process incoming message publication requests
Runnable runnable = new Runnable() {
@SuppressWarnings("ConstantConditions")
@SuppressWarnings({"ConstantConditions", "UnnecessaryLocalVariable"})
@Override
public
void run() {

View File

@ -35,10 +35,10 @@ import java.util.concurrent.locks.LockSupport;
public final
class AsyncDisruptor implements Synchrony {
private WorkProcessor[] workProcessors;
private MessageHandler[] handlers;
private RingBuffer<MessageHolder> ringBuffer;
private Sequence workSequence;
private final WorkProcessor[] workProcessors;
private final MessageHandler[] handlers;
private final RingBuffer<MessageHolder> ringBuffer;
private final Sequence workSequence;
public
AsyncDisruptor(final int numberOfThreads, final ErrorHandlingSupport errorHandler, final Synchrony syncPublication) {

View File

@ -32,29 +32,4 @@ class MessageHolder {
public
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;
}
}

View File

@ -16,6 +16,7 @@
package dorkbox.util.messagebus.utils;
import com.esotericsoftware.kryo.util.IdentityMap;
import dorkbox.util.messagebus.subscription.SubscriptionManager;
import java.lang.reflect.Array;
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
*/
public
ClassUtils(final float loadFactor) {
this.arrayCache = new IdentityMap<Class<?>, Class<?>>(32, loadFactor);
this.superClassesCache = new IdentityMap<Class<?>, Class<?>[]>(32, loadFactor);
ClassUtils() {
this.arrayCache = new IdentityMap<Class<?>, Class<?>>(32, SubscriptionManager.LOAD_FACTOR);
this.superClassesCache = new IdentityMap<Class<?>, Class<?>[]>(32, SubscriptionManager.LOAD_FACTOR);
}
/**
@ -58,7 +59,7 @@ class ClassUtils {
public
Class<?>[] getSuperClasses(final Class<?> clazz) {
// 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);
@ -115,7 +116,7 @@ class ClassUtils {
public
Class<?> getArrayClass(final Class<?> c) {
// 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);
@ -141,4 +142,10 @@ class ClassUtils {
this.arrayCache.clear();
this.superClassesCache.clear();
}
@SuppressWarnings("unchecked")
private static
<T> T cast(Object obj) {
return (T) obj;
}
}

View File

@ -56,6 +56,9 @@ import java.util.Collection;
public final
class ReflectionUtils {
private static final Method[] EMPTY_METHODS = new Method[0];
private static final Class<?>[] EMPTY_CLASSES = new Class<?>[0];
private
ReflectionUtils() {
}
@ -65,7 +68,7 @@ class ReflectionUtils {
ArrayList<Method> methods = new ArrayList<Method>();
getMethods(target, methods);
return methods.toArray(new Method[0]);
return methods.toArray(EMPTY_METHODS);
}
private static
@ -111,7 +114,7 @@ class ReflectionUtils {
* @return A set of classes, each representing a super type of the root class
*/
public static
Class<?>[] getSuperTypes2(Class<?> from) {
Class<?>[] getSuperTypes(Class<?> from) {
ArrayList<Class<?>> superclasses = new ArrayList<Class<?>>();
collectInterfaces(from, superclasses);
@ -122,25 +125,10 @@ class ReflectionUtils {
collectInterfaces(from, superclasses);
}
return superclasses.toArray(new Class<?>[0]);
return superclasses.toArray(EMPTY_CLASSES);
}
public static Class[] getSuperTypes(Class from) {
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
private static
void collectInterfaces(Class<?> from, Collection<Class<?>> accumulator) {
for (Class<?> intface : from.getInterfaces()) {
accumulator.add(intface);
@ -193,8 +181,7 @@ class ReflectionUtils {
public static
<A extends Annotation> A getAnnotation(AnnotatedElement from, Class<A> annotationType) {
A annotation = getAnnotation(from, annotationType, new IdentityMap<AnnotatedElement, Boolean>());
return annotation;
return getAnnotation(from, annotationType, new IdentityMap<AnnotatedElement, Boolean>());
}
//

View File

@ -32,8 +32,6 @@ public class MultiTreeTest extends AssertSupport {
final MultiClass d = tree.get(Object.class, Object.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)
assertNotNull(a);
@ -41,7 +39,5 @@ public class MultiTreeTest extends AssertSupport {
assertNotNull(c);
assertNotNull(d);
assertNotNull(e);
assertNotNull(f);
assertNotNull(g);
}
}