Added intellij support. Compiled as java6, supports java8 ConcurrentHashMap

This commit is contained in:
nathan 2015-06-28 00:16:38 +02:00
parent 894da4c980
commit 8f312a8012
42 changed files with 724 additions and 449 deletions

View File

@ -3,7 +3,7 @@ package dorkbox.util.messagebus;
import org.jctools.queues.MpmcArrayQueue; import org.jctools.queues.MpmcArrayQueue;
import org.jctools.util.UnsafeAccess; import org.jctools.util.UnsafeAccess;
import java.util.concurrent.ThreadLocalRandom; import java.util.Random;
final final
@ -38,14 +38,6 @@ class MpmcMultiTransferArrayQueue extends MpmcArrayQueue<Object> {
*/ */
private static final int PARK_UNTIMED_SPINS = PARK_TIMED_SPINS * 16; private static final int PARK_UNTIMED_SPINS = PARK_TIMED_SPINS * 16;
private final int consumerCount;
public
MpmcMultiTransferArrayQueue(final int consumerCount) {
super(1024); // must be power of 2
this.consumerCount = consumerCount;
}
private static final ThreadLocal<Object> nodeThreadLocal = new ThreadLocal<Object>() { private static final ThreadLocal<Object> nodeThreadLocal = new ThreadLocal<Object>() {
@Override @Override
protected protected
@ -54,6 +46,22 @@ class MpmcMultiTransferArrayQueue extends MpmcArrayQueue<Object> {
} }
}; };
private static final ThreadLocal<Random> randomThreadLocal = new ThreadLocal<Random>() {
@Override
protected
Random initialValue() {
return new Random();
}
};
private final int consumerCount;
public
MpmcMultiTransferArrayQueue(final int consumerCount) {
super(1024); // must be power of 2
this.consumerCount = consumerCount;
}
/** /**
* PRODUCER method * PRODUCER method
@ -714,7 +722,7 @@ class MpmcMultiTransferArrayQueue extends MpmcArrayQueue<Object> {
private private
void park(final Object node, final Thread myThread) throws InterruptedException { void park(final Object node, final Thread myThread) throws InterruptedException {
int spins = -1; // initialized after first item and cancel checks int spins = -1; // initialized after first item and cancel checks
ThreadLocalRandom randomYields = null; // bound if needed Random randomYields = null; // bound if needed
for (; ; ) { for (; ; ) {
if (MultiNode.lvThread(node) == null) { if (MultiNode.lvThread(node) == null) {
@ -725,7 +733,7 @@ class MpmcMultiTransferArrayQueue extends MpmcArrayQueue<Object> {
} }
else if (spins < 0) { else if (spins < 0) {
spins = PARK_UNTIMED_SPINS; spins = PARK_UNTIMED_SPINS;
randomYields = ThreadLocalRandom.current(); randomYields = randomThreadLocal.get();
} }
else if (spins > 0) { else if (spins > 0) {
if (randomYields.nextInt(1024) == 0) { if (randomYields.nextInt(1024) == 0) {

View File

@ -1,10 +1,6 @@
package dorkbox.util.messagebus.annotations; package dorkbox.util.messagebus.annotations;
import java.lang.annotation.ElementType; import java.lang.annotation.*;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/** /**
* Mark any method of any class(=listener) as a message handler and configure the handler * Mark any method of any class(=listener) as a message handler and configure the handler
@ -17,8 +13,9 @@ import java.lang.annotation.Target;
*/ */
@Retention(value = RetentionPolicy.RUNTIME) @Retention(value = RetentionPolicy.RUNTIME)
@Inherited @Inherited
@Target(value = {ElementType.METHOD,ElementType.ANNOTATION_TYPE}) @Target(value = {ElementType.METHOD, ElementType.ANNOTATION_TYPE})
public @interface Handler { public
@interface Handler {
/** /**
* Define whether or not the handler accepts variable arguments it declares in its signature. * Define whether or not the handler accepts variable arguments it declares in its signature.

View File

@ -1,23 +1,18 @@
package dorkbox.util.messagebus.annotations; package dorkbox.util.messagebus.annotations;
import java.lang.annotation.ElementType; import java.lang.annotation.*;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/** /**
*
* This annotation is meant to carry configuration that is shared among all instances of the annotated * This annotation is meant to carry configuration that is shared among all instances of the annotated
* listener. Supported configurations are: * listener. Supported configurations are:
* * <p/>
* Reference type: The bus will use either strong or weak references to its registered listeners, * Reference type: The bus will use either strong or weak references to its registered listeners,
* depending on which reference type (@see References) is set * depending on which reference type (@see References) is set
* *
* @author bennidi * @author bennidi
*/ */
@Retention(value = RetentionPolicy.RUNTIME) @Retention(value = RetentionPolicy.RUNTIME)
@Target(value = {ElementType.TYPE, ElementType.ANNOTATION_TYPE}) @Target(value = {ElementType.TYPE, ElementType.ANNOTATION_TYPE})
@Inherited @Inherited
public @interface Listener { public
} @interface Listener {}

View File

@ -1,10 +1,6 @@
package dorkbox.util.messagebus.annotations; package dorkbox.util.messagebus.annotations;
import java.lang.annotation.ElementType; import java.lang.annotation.*;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/** /**
* A handler marked with this annotation is guaranteed to be invoked in a thread-safe manner, that is, no * A handler marked with this annotation is guaranteed to be invoked in a thread-safe manner, that is, no
@ -12,16 +8,14 @@ import java.lang.annotation.Target;
* listener until the handler completed. It is equal to wrapping the handler code in a synchronized{} block. * listener until the handler completed. It is equal to wrapping the handler code in a synchronized{} block.
* This feature will reduce performance of message publication. Try to avoid shared mutable state whenever possible * This feature will reduce performance of message publication. Try to avoid shared mutable state whenever possible
* and use immutable data instead. * and use immutable data instead.
* * <p/>
* Note: Unsynchronized handlers may still be invoked concurrently with synchronized ones * Note: Unsynchronized handlers may still be invoked concurrently with synchronized ones
* *
*
*
* @author bennidi * @author bennidi
* Date: 3/31/13 * Date: 3/31/13
*/ */
@Retention(value = RetentionPolicy.RUNTIME) @Retention(value = RetentionPolicy.RUNTIME)
@Inherited @Inherited
@Target(value = {ElementType.METHOD, ElementType.ANNOTATION_TYPE}) @Target(value = {ElementType.METHOD, ElementType.ANNOTATION_TYPE})
public @interface Synchronized { public
} @interface Synchronized {}

View File

@ -16,7 +16,8 @@ import java.util.concurrent.atomic.AtomicLong;
* @author bennidi * @author bennidi
* Date: 2/12/12 * Date: 2/12/12
*/ */
public abstract class AbstractConcurrentSet<T> implements Set<T> { public abstract
class AbstractConcurrentSet<T> implements Set<T> {
private static final AtomicLong id = new AtomicLong(); private static final AtomicLong id = new AtomicLong();
private final transient long ID = id.getAndIncrement(); private final transient long ID = id.getAndIncrement();
@ -28,14 +29,17 @@ public abstract class AbstractConcurrentSet<T> implements Set<T> {
volatile long z0, z1, z2, z4, z5, z6 = 7L; volatile long z0, z1, z2, z4, z5, z6 = 7L;
protected AbstractConcurrentSet(Map<T, ISetEntry<T>> entries) { protected
AbstractConcurrentSet(Map<T, ISetEntry<T>> entries) {
this.entries = entries; this.entries = entries;
} }
protected abstract Entry<T> createEntry(T value, Entry<T> next); protected abstract
Entry<T> createEntry(T value, Entry<T> next);
@Override @Override
public boolean add(T element) { public
boolean add(T element) {
if (element == null) { if (element == null) {
return false; return false;
} }
@ -62,7 +66,8 @@ public abstract class AbstractConcurrentSet<T> implements Set<T> {
} }
@Override @Override
public boolean contains(Object element) { public
boolean contains(Object element) {
final StampedLock lock = this.lock; final StampedLock lock = this.lock;
long stamp = lock.readLock(); long stamp = lock.readLock();
@ -73,7 +78,8 @@ public abstract class AbstractConcurrentSet<T> implements Set<T> {
return entry != null && entry.getValue() != null; return entry != null && entry.getValue() != null;
} }
private boolean insert(T element) { private
boolean insert(T element) {
if (!this.entries.containsKey(element)) { if (!this.entries.containsKey(element)) {
this.head = createEntry(element, this.head); this.head = createEntry(element, this.head);
this.entries.put(element, this.head); this.entries.put(element, this.head);
@ -83,17 +89,20 @@ public abstract class AbstractConcurrentSet<T> implements Set<T> {
} }
@Override @Override
public int size() { public
int size() {
return this.entries.size(); return this.entries.size();
} }
@Override @Override
public boolean isEmpty() { public
boolean isEmpty() {
return this.head == null; return this.head == null;
} }
@Override @Override
public boolean addAll(Collection<? extends T> elements) { public
boolean addAll(Collection<? extends T> elements) {
StampedLock lock = this.lock; StampedLock lock = this.lock;
boolean changed = false; boolean changed = false;
@ -116,7 +125,8 @@ public abstract class AbstractConcurrentSet<T> implements Set<T> {
* @return TRUE if the element was successfully removed * @return TRUE if the element was successfully removed
*/ */
@Override @Override
public boolean remove(Object element) { public
boolean remove(Object element) {
StampedLock lock = this.lock; StampedLock lock = this.lock;
long stamp = lock.readLock(); long stamp = lock.readLock();
@ -126,13 +136,15 @@ public abstract class AbstractConcurrentSet<T> implements Set<T> {
if (entry == null || entry.getValue() == null) { if (entry == null || entry.getValue() == null) {
return false; // fast exit return false; // fast exit
} else { }
else {
stamp = lock.writeLock(); stamp = lock.writeLock();
try { try {
if (entry != this.head) { if (entry != this.head) {
entry.remove(); entry.remove();
} else { }
else {
// if it was second, now it's first // if it was second, now it's first
this.head = this.head.next(); this.head = this.head.next();
//oldHead.clear(); // optimize for GC not possible because of potentially running iterators //oldHead.clear(); // optimize for GC not possible because of potentially running iterators
@ -146,32 +158,38 @@ public abstract class AbstractConcurrentSet<T> implements Set<T> {
} }
@Override @Override
public Object[] toArray() { public
Object[] toArray() {
return this.entries.entrySet().toArray(); return this.entries.entrySet().toArray();
} }
@Override @Override
public <T2> T2[] toArray(T2[] a) { public
<T2> T2[] toArray(T2[] a) {
return this.entries.entrySet().toArray(a); return this.entries.entrySet().toArray(a);
} }
@Override @Override
public boolean containsAll(Collection<?> c) { public
boolean containsAll(Collection<?> c) {
throw new UnsupportedOperationException("Not implemented"); throw new UnsupportedOperationException("Not implemented");
} }
@Override @Override
public boolean removeAll(Collection<?> c) { public
boolean removeAll(Collection<?> c) {
throw new UnsupportedOperationException("Not implemented"); throw new UnsupportedOperationException("Not implemented");
} }
@Override @Override
public boolean retainAll(Collection<?> c) { public
boolean retainAll(Collection<?> c) {
throw new UnsupportedOperationException("Not implemented"); throw new UnsupportedOperationException("Not implemented");
} }
@Override @Override
public void clear() { public
void clear() {
StampedLock lock = this.lock; StampedLock lock = this.lock;
long stamp = lock.writeLock(); long stamp = lock.writeLock();
@ -181,7 +199,8 @@ public abstract class AbstractConcurrentSet<T> implements Set<T> {
} }
@Override @Override
public int hashCode() { public
int hashCode() {
final int prime = 31; final int prime = 31;
int result = 1; int result = 1;
result = prime * result + (int) (this.ID ^ this.ID >>> 32); result = prime * result + (int) (this.ID ^ this.ID >>> 32);
@ -189,7 +208,8 @@ public abstract class AbstractConcurrentSet<T> implements Set<T> {
} }
@Override @Override
public boolean equals(Object obj) { public
boolean equals(Object obj) {
if (this == obj) { if (this == obj) {
return true; return true;
} }

View File

@ -11,34 +11,40 @@ import java.util.Arrays;
* @author dorkbox, llc * @author dorkbox, llc
* Date: 2/2/15 * Date: 2/2/15
*/ */
public final class DeadMessage { public final
class DeadMessage {
private final Object[] relatedMessages; private final Object[] relatedMessages;
public DeadMessage(Object message) { public
DeadMessage(Object message) {
this.relatedMessages = new Object[1]; this.relatedMessages = new Object[1];
this.relatedMessages[0] = message; this.relatedMessages[0] = message;
} }
public DeadMessage(Object message1, Object message2) { public
DeadMessage(Object message1, Object message2) {
this.relatedMessages = new Object[2]; this.relatedMessages = new Object[2];
this.relatedMessages[0] = message1; this.relatedMessages[0] = message1;
this.relatedMessages[1] = message2; this.relatedMessages[1] = message2;
} }
public DeadMessage(Object message1, Object message2, Object message3) { public
DeadMessage(Object message1, Object message2, Object message3) {
this.relatedMessages = new Object[3]; this.relatedMessages = new Object[3];
this.relatedMessages[0] = message1; this.relatedMessages[0] = message1;
this.relatedMessages[1] = message2; this.relatedMessages[1] = message2;
this.relatedMessages[2] = message3; this.relatedMessages[2] = message3;
} }
public DeadMessage(Object[] messages) { public
DeadMessage(Object[] messages) {
this.relatedMessages = Arrays.copyOf(messages, messages.length); this.relatedMessages = Arrays.copyOf(messages, messages.length);
} }
public Object[] getMessages() { public
Object[] getMessages() {
return this.relatedMessages; return this.relatedMessages;
} }
} }

View File

@ -32,7 +32,7 @@ public class HashMapTree<KEY, VALUE> {
* can be overridden to provide a custom backing map * can be overridden to provide a custom backing map
*/ */
protected Map<KEY, HashMapTree<KEY, VALUE>> createChildren(int defaultSize, float loadFactor) { protected Map<KEY, HashMapTree<KEY, VALUE>> createChildren(int defaultSize, float loadFactor) {
return JavaVersionAdapter.get.concurrentMap(defaultSize, loadFactor, 1); return JavaVersionAdapter.concurrentMap(defaultSize, loadFactor, 1);
} }
public final VALUE getValue() { public final VALUE getValue() {

View File

@ -13,26 +13,28 @@ import java.util.Arrays;
* Any method in any class annotated with the @Handler annotation represents a message handler. The class that contains * Any method in any class annotated with the @Handler annotation represents a message handler. The class that contains
* the handler is called a message listener and more generally, any class containing a message handler in its class hierarchy * the handler is called a message listener and more generally, any class containing a message handler in its class hierarchy
* defines such a message listener. * defines such a message listener.
* <p> * <p/>
* <p> * <p/>
* Note: When sending messages to a handler that is of type ARRAY (either an object of type array, or a vararg), the JVM cannot * Note: When sending messages to a handler that is of type ARRAY (either an object of type array, or a vararg), the JVM cannot
* tell the difference (the message that is being sent), if it is a vararg or array. * tell the difference (the message that is being sent), if it is a vararg or array.
* <p> * <p/>
* <p> * <p/>
* BECAUSE OF THIS, we always treat the two the same * BECAUSE OF THIS, we always treat the two the same
* <p> * <p/>
* <p> * <p/>
* *
* @author bennidi * @author bennidi
* Date: 11/14/12 * Date: 11/14/12
* @author dorkbox, llc * @author dorkbox, llc
* Date: 2/2/15 * Date: 2/2/15
*/ */
public class MessageHandler { public
class MessageHandler {
// publish all listeners defined by the given class (includes // publish all listeners defined by the given class (includes
// listeners defined in super classes) // listeners defined in super classes)
public static MessageHandler[] get(final Class<?> target) { public static
MessageHandler[] get(final Class<?> target) {
// publish all handlers (this will include all (inherited) methods directly annotated using @Handler) // publish all handlers (this will include all (inherited) methods directly annotated using @Handler)
final Method[] allMethods = ReflectionUtils.getMethods(target); final Method[] allMethods = ReflectionUtils.getMethods(target);
@ -41,7 +43,7 @@ public class MessageHandler {
final ArrayList<MessageHandler> finalMethods = new ArrayList<MessageHandler>(length); final ArrayList<MessageHandler> finalMethods = new ArrayList<MessageHandler>(length);
Method method; Method method;
for (int i=0;i<length;i++) { for (int i = 0; i < length; i++) {
method = allMethods[i]; method = allMethods[i];
// retain only those that are at the bottom of their respective class hierarchy (deepest overriding method) // retain only those that are at the bottom of their respective class hierarchy (deepest overriding method)
@ -79,7 +81,8 @@ public class MessageHandler {
private final boolean isSynchronized; private final boolean isSynchronized;
public MessageHandler(Method handler, Handler handlerConfig) { public
MessageHandler(Method handler, Handler handlerConfig) {
super(); super();
if (handler == null) { if (handler == null) {
@ -92,7 +95,7 @@ public class MessageHandler {
this.methodIndex = this.handler.getIndex(handler.getName(), handledMessages); this.methodIndex = this.handler.getIndex(handler.getName(), handledMessages);
this.acceptsSubtypes = handlerConfig.acceptSubtypes(); this.acceptsSubtypes = handlerConfig.acceptSubtypes();
this.isSynchronized = ReflectionUtils.getAnnotation(handler, Synchronized.class) != null; this.isSynchronized = ReflectionUtils.getAnnotation(handler, Synchronized.class) != null;
this.handledMessages = handledMessages; this.handledMessages = handledMessages;
if (handledMessages.length == 1 && handledMessages[0].isArray() && handlerConfig.acceptVarargs()) { if (handledMessages.length == 1 && handledMessages[0].isArray() && handlerConfig.acceptVarargs()) {
@ -103,36 +106,44 @@ public class MessageHandler {
} }
} }
public final boolean isSynchronized() { public final
boolean isSynchronized() {
return this.isSynchronized; return this.isSynchronized;
} }
public final MethodAccess getHandler() { public final
MethodAccess getHandler() {
return this.handler; return this.handler;
} }
public final int getMethodIndex() { public final
int getMethodIndex() {
return this.methodIndex; return this.methodIndex;
} }
public final Class<?>[] getHandledMessages() { public final
Class<?>[] getHandledMessages() {
return this.handledMessages; return this.handledMessages;
} }
public final Class<?> getVarArgClass() { public final
Class<?> getVarArgClass() {
return this.varArgClass; return this.varArgClass;
} }
public final boolean acceptsSubtypes() { public final
boolean acceptsSubtypes() {
return this.acceptsSubtypes; return this.acceptsSubtypes;
} }
public final boolean acceptsVarArgs() { public final
boolean acceptsVarArgs() {
return this.varArgClass != null; return this.varArgClass != null;
} }
@Override @Override
public final int hashCode() { public final
int hashCode() {
final int prime = 31; final int prime = 31;
int result = 1; int result = 1;
result = prime * result + (this.acceptsSubtypes ? 1231 : 1237); result = prime * result + (this.acceptsSubtypes ? 1231 : 1237);
@ -143,7 +154,8 @@ public class MessageHandler {
} }
@Override @Override
public final boolean equals(Object obj) { public final
boolean equals(Object obj) {
if (this == obj) { if (this == obj) {
return true; return true;
} }
@ -164,7 +176,8 @@ public class MessageHandler {
if (other.handler != null) { if (other.handler != null) {
return false; return false;
} }
} else if (!this.handler.equals(other.handler)) { }
else if (!this.handler.equals(other.handler)) {
return false; return false;
} }
if (this.isSynchronized != other.isSynchronized) { if (this.isSynchronized != other.isSynchronized) {

View File

@ -1,4 +1,5 @@
package dorkbox.util.messagebus.common; package dorkbox.util.messagebus.common;
import java.util.HashMap; import java.util.HashMap;
import java.util.Iterator; import java.util.Iterator;
import java.util.Map; import java.util.Map;
@ -10,33 +11,40 @@ import java.util.Map;
* @author bennidi * @author bennidi
* Date: 2/12/12 * Date: 2/12/12
*/ */
public class StrongConcurrentSet<T> extends AbstractConcurrentSet<T> { public
class StrongConcurrentSet<T> extends AbstractConcurrentSet<T> {
public StrongConcurrentSet() { public
StrongConcurrentSet() {
this(16, 0.75f); this(16, 0.75f);
} }
public StrongConcurrentSet(int size, float loadFactor) { public
StrongConcurrentSet(int size, float loadFactor) {
this(new HashMap<T, ISetEntry<T>>(size, loadFactor)); this(new HashMap<T, ISetEntry<T>>(size, loadFactor));
} }
public StrongConcurrentSet(Map<T, ISetEntry<T>> entries) { public
StrongConcurrentSet(Map<T, ISetEntry<T>> entries) {
super(entries); super(entries);
} }
@Override @Override
public Iterator<T> iterator() { public
Iterator<T> iterator() {
return new Iterator<T>() { return new Iterator<T>() {
private ISetEntry<T> current = StrongConcurrentSet.this.head; private ISetEntry<T> current = StrongConcurrentSet.this.head;
@Override @Override
public boolean hasNext() { public
boolean hasNext() {
return this.current != null; return this.current != null;
} }
@Override @Override
public T next() { public
T next() {
if (this.current == null) { if (this.current == null) {
return null; return null;
} }
@ -48,7 +56,8 @@ public class StrongConcurrentSet<T> extends AbstractConcurrentSet<T> {
} }
@Override @Override
public void remove() { public
void remove() {
if (this.current == null) { if (this.current == null) {
return; return;
} }
@ -60,27 +69,32 @@ public class StrongConcurrentSet<T> extends AbstractConcurrentSet<T> {
} }
@Override @Override
protected Entry<T> createEntry(T value, Entry<T> next) { protected
Entry<T> createEntry(T value, Entry<T> next) {
return next != null ? new StrongEntry<T>(value, next) : new StrongEntry<T>(value); return next != null ? new StrongEntry<T>(value, next) : new StrongEntry<T>(value);
} }
public static class StrongEntry<T> extends Entry<T> { public static
class StrongEntry<T> extends Entry<T> {
private T value; private T value;
private StrongEntry(T value, Entry<T> next) { private
StrongEntry(T value, Entry<T> next) {
super(next); super(next);
this.value = value; this.value = value;
} }
private StrongEntry(T value) { private
StrongEntry(T value) {
super(); super();
this.value = value; this.value = value;
} }
@Override @Override
public T getValue() { public
T getValue() {
return this.value; return this.value;
} }
} }

View File

@ -13,11 +13,11 @@ public class StrongConcurrentSetV8<T> extends StrongConcurrentSet<T> {
public StrongConcurrentSetV8(int size, float loadFactor) { public StrongConcurrentSetV8(int size, float loadFactor) {
// 1 for the stripe size, because that is the max concurrency with our concurrent set (since it uses R/W locks) // 1 for the stripe size, because that is the max concurrency with our concurrent set (since it uses R/W locks)
super(JavaVersionAdapter.get.<T, ISetEntry<T>>concurrentMap(size, loadFactor, 16)); super(JavaVersionAdapter.<T, ISetEntry<T>>concurrentMap(size, loadFactor, 16));
} }
public StrongConcurrentSetV8(int size, float loadFactor, int stripeSize) { public StrongConcurrentSetV8(int size, float loadFactor, int stripeSize) {
// 1 for the stripe size, because that is the max concurrency with our concurrent set (since it uses R/W locks) // 1 for the stripe size, because that is the max concurrency with our concurrent set (since it uses R/W locks)
super(JavaVersionAdapter.get.<T, ISetEntry<T>>concurrentMap(size, loadFactor, stripeSize)); super(JavaVersionAdapter.<T, ISetEntry<T>>concurrentMap(size, loadFactor, stripeSize));
} }
} }

View File

@ -13,15 +13,18 @@ import java.util.WeakHashMap;
* @author bennidi * @author bennidi
* Date: 2/12/12 * Date: 2/12/12
*/ */
public class WeakConcurrentSet<T> extends AbstractConcurrentSet<T>{ public
class WeakConcurrentSet<T> extends AbstractConcurrentSet<T> {
public WeakConcurrentSet() { public
WeakConcurrentSet() {
super(new WeakHashMap<T, ISetEntry<T>>()); super(new WeakHashMap<T, ISetEntry<T>>());
} }
@Override @Override
public Iterator<T> iterator() { public
Iterator<T> iterator() {
return new Iterator<T>() { return new Iterator<T>() {
// the current list element of this iterator // the current list element of this iterator
@ -31,20 +34,20 @@ public class WeakConcurrentSet<T> extends AbstractConcurrentSet<T>{
// this method will remove all orphaned entries // this method will remove all orphaned entries
// until it finds the first entry whose value has not yet been garbage collected // until it finds the first entry whose value has not yet been garbage collected
// the method assumes that the current element is already orphaned and will remove it // the method assumes that the current element is already orphaned and will remove it
private void removeOrphans(){ private
void removeOrphans() {
StampedLock lock = WeakConcurrentSet.this.lock; StampedLock lock = WeakConcurrentSet.this.lock;
long stamp = lock.writeLock(); long stamp = lock.writeLock();
// final Lock writeLock = WeakConcurrentSet.this.lock.writeLock(); // final Lock writeLock = WeakConcurrentSet.this.lock.writeLock();
// writeLock.lock(); // writeLock.lock();
try{ try {
do { do {
ISetEntry<T> orphaned = this.current; ISetEntry<T> orphaned = this.current;
this.current = this.current.next(); this.current = this.current.next();
orphaned.remove(); orphaned.remove();
} while(this.current != null && this.current.getValue() == null); } while (this.current != null && this.current.getValue() == null);
} } finally {
finally {
lock.unlockWrite(stamp); lock.unlockWrite(stamp);
// writeLock.unlock(); // writeLock.unlock();
} }
@ -52,7 +55,8 @@ public class WeakConcurrentSet<T> extends AbstractConcurrentSet<T>{
@Override @Override
public boolean hasNext() { public
boolean hasNext() {
if (this.current == null) { if (this.current == null) {
return false; return false;
} }
@ -61,13 +65,15 @@ public class WeakConcurrentSet<T> extends AbstractConcurrentSet<T>{
// because a null value indicates that the value has been garbage collected // because a null value indicates that the value has been garbage collected
removeOrphans(); removeOrphans();
return this.current != null; // if any entry is left then it will have a value return this.current != null; // if any entry is left then it will have a value
} else { }
else {
return true; return true;
} }
} }
@Override @Override
public T next() { public
T next() {
if (this.current == null) { if (this.current == null) {
return null; return null;
} }
@ -75,14 +81,16 @@ public class WeakConcurrentSet<T> extends AbstractConcurrentSet<T>{
if (value == null) { // auto-removal of orphan references if (value == null) { // auto-removal of orphan references
removeOrphans(); removeOrphans();
return next(); return next();
} else { }
else {
this.current = this.current.next(); this.current = this.current.next();
return value; return value;
} }
} }
@Override @Override
public void remove() { public
void remove() {
//throw new UnsupportedOperationException("Explicit removal of set elements is only allowed via the controlling set. Sorry!"); //throw new UnsupportedOperationException("Explicit removal of set elements is only allowed via the controlling set. Sorry!");
if (this.current == null) { if (this.current == null) {
return; return;
@ -95,27 +103,32 @@ public class WeakConcurrentSet<T> extends AbstractConcurrentSet<T>{
} }
@Override @Override
protected Entry<T> createEntry(T value, Entry<T> next) { protected
Entry<T> createEntry(T value, Entry<T> next) {
return next != null ? new WeakEntry<T>(value, next) : new WeakEntry<T>(value); return next != null ? new WeakEntry<T>(value, next) : new WeakEntry<T>(value);
} }
public static class WeakEntry<T> extends Entry<T> { public static
class WeakEntry<T> extends Entry<T> {
private WeakReference<T> value; private WeakReference<T> value;
private WeakEntry(T value, Entry<T> next) { private
WeakEntry(T value, Entry<T> next) {
super(next); super(next);
this.value = new WeakReference<T>(value); this.value = new WeakReference<T>(value);
} }
private WeakEntry(T value) { private
WeakEntry(T value) {
super(); super();
this.value = new WeakReference<T>(value); this.value = new WeakReference<T>(value);
} }
@Override @Override
public T getValue() { public
T getValue() {
return this.value.get(); return this.value.get();
} }
} }

View File

@ -21,7 +21,6 @@ import java.util.Map;
import java.util.NoSuchElementException; import java.util.NoSuchElementException;
import java.util.Set; import java.util.Set;
import java.util.concurrent.ConcurrentMap; import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.LockSupport; import java.util.concurrent.locks.LockSupport;
import java.util.concurrent.locks.ReentrantLock; import java.util.concurrent.locks.ReentrantLock;

View File

@ -5,10 +5,12 @@ import java.util.concurrent.ConcurrentMap;
/** /**
* *
*/ */
public class Java7Adapter extends JavaVersionAdapter { public
class Java6Adapter implements MapAdapter {
@Override @Override
public final <K, V> ConcurrentMap<K, V> concurrentMap(final int size, final float loadFactor, final int stripeSize) { public final
<K, V> ConcurrentMap<K, V> concurrentMap(final int size, final float loadFactor, final int stripeSize) {
return new ConcurrentHashMapV8<K, V>(size, loadFactor, stripeSize); return new ConcurrentHashMapV8<K, V>(size, loadFactor, stripeSize);
} }
} }

View File

@ -3,9 +3,11 @@ package dorkbox.util.messagebus.common.adapter;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap; import java.util.concurrent.ConcurrentMap;
public class Java8Adapter extends JavaVersionAdapter { public
class Java8Adapter implements MapAdapter {
@Override @Override
public final <K, V> ConcurrentMap<K, V> concurrentMap(final int size, final float loadFactor, final int stripeSize) { public final
<K, V> ConcurrentMap<K, V> concurrentMap(final int size, final float loadFactor, final int stripeSize) {
return new ConcurrentHashMap<K, V>(size, loadFactor, stripeSize); return new ConcurrentHashMap<K, V>(size, loadFactor, stripeSize);
} }
} }

View File

@ -1,29 +1,29 @@
package dorkbox.util.messagebus.common.adapter; package dorkbox.util.messagebus.common.adapter;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap; import java.util.concurrent.ConcurrentMap;
public abstract class JavaVersionAdapter { public
class JavaVersionAdapter {
public static final JavaVersionAdapter get; private static final MapAdapter get;
static { static {
// get = new Java7Adapter(); MapAdapter adapter;
get = new Java8Adapter(); try {
Class.forName("java.util.concurrent.locks.StampedLock");
adapter = new Java8Adapter();
} catch (Exception e) {
adapter = new Java6Adapter();
}
get = adapter;
} }
public static
public abstract <K, V> ConcurrentMap<K, V> concurrentMap(final int size, final float loadFactor, final int stripeSize); <K, V> ConcurrentMap<K, V> concurrentMap(final int size, final float loadFactor, final int stripeSize) {
return get.concurrentMap(size, loadFactor, stripeSize);
public <K, V> Map<K, V> hashMap(final int size, final float loadFactor) {
return new ConcurrentHashMap<K, V>(size, loadFactor, 1);
} }
} }

View File

@ -0,0 +1,11 @@
package dorkbox.util.messagebus.common.adapter;
import java.util.concurrent.ConcurrentMap;
/**
*
*/
public
interface MapAdapter {
<K, V> ConcurrentMap<K, V> concurrentMap(final int size, final float loadFactor, final int stripeSize);
}

View File

@ -6,7 +6,7 @@
package dorkbox.util.messagebus.common.adapter; package dorkbox.util.messagebus.common.adapter;
import java.util.concurrent.ThreadLocalRandom; import java.util.Random;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.Lock;
@ -282,6 +282,14 @@ public class StampedLock implements java.io.Serializable {
private static final int RMODE = 0; private static final int RMODE = 0;
private static final int WMODE = 1; private static final int WMODE = 1;
private static final ThreadLocal<Random> randomThreadLocal = new ThreadLocal<Random>() {
@Override
protected
Random initialValue() {
return new Random();
}
};
/** Wait nodes */ /** Wait nodes */
static final class WNode { static final class WNode {
volatile WNode prev; volatile WNode prev;
@ -308,6 +316,7 @@ public class StampedLock implements java.io.Serializable {
/** extra reader count when state read count saturated */ /** extra reader count when state read count saturated */
private transient int readerOverflow; private transient int readerOverflow;
/** /**
* Creates a new lock, initially in unlocked state. * Creates a new lock, initially in unlocked state.
*/ */
@ -1004,7 +1013,7 @@ public class StampedLock implements java.io.Serializable {
return s; return s;
} }
} }
else if ((ThreadLocalRandom.current().nextInt() & else if ((randomThreadLocal.get().nextInt() &
OVERFLOW_YIELD_RATE) == 0) { OVERFLOW_YIELD_RATE) == 0) {
Thread.yield(); Thread.yield();
} }
@ -1032,7 +1041,7 @@ public class StampedLock implements java.io.Serializable {
return next; return next;
} }
} }
else if ((ThreadLocalRandom.current().nextInt() & else if ((randomThreadLocal.get().nextInt() &
OVERFLOW_YIELD_RATE) == 0) { OVERFLOW_YIELD_RATE) == 0) {
Thread.yield(); Thread.yield();
} }
@ -1084,7 +1093,7 @@ public class StampedLock implements java.io.Serializable {
else if (spins < 0) { else if (spins < 0) {
spins = m == WBIT && this.wtail == this.whead ? SPINS : 0; spins = m == WBIT && this.wtail == this.whead ? SPINS : 0;
} else if (spins > 0) { } else if (spins > 0) {
if (ThreadLocalRandom.current().nextInt() >= 0) { if (randomThreadLocal.get().nextInt() >= 0) {
--spins; --spins;
} }
} }
@ -1122,7 +1131,7 @@ public class StampedLock implements java.io.Serializable {
return ns; return ns;
} }
} }
else if (ThreadLocalRandom.current().nextInt() >= 0 && else if (randomThreadLocal.get().nextInt() >= 0 &&
--k <= 0) { --k <= 0) {
break; break;
} }
@ -1198,7 +1207,7 @@ public class StampedLock implements java.io.Serializable {
return ns; return ns;
} else if (m >= WBIT) { } else if (m >= WBIT) {
if (spins > 0) { if (spins > 0) {
if (ThreadLocalRandom.current().nextInt() >= 0) { if (randomThreadLocal.get().nextInt() >= 0) {
--spins; --spins;
} }
} }
@ -1307,7 +1316,7 @@ public class StampedLock implements java.io.Serializable {
return ns; return ns;
} }
else if (m >= WBIT && else if (m >= WBIT &&
ThreadLocalRandom.current().nextInt() >= 0 && --k <= 0) { randomThreadLocal.get().nextInt() >= 0 && --k <= 0) {
break; break;
} }
} }

View File

@ -15,7 +15,8 @@ import java.util.concurrent.atomic.AtomicLong;
* structure. Remove operations can affect any running iterator such that a removed element that has not yet * structure. Remove operations can affect any running iterator such that a removed element that has not yet
* been reached by the iterator will not appear in that iterator anymore. * been reached by the iterator will not appear in that iterator anymore.
*/ */
public class ConcurrentSet<T> extends ConcurrentLinkedQueue2<T> { public
class ConcurrentSet<T> extends ConcurrentLinkedQueue2<T> {
private static final long serialVersionUID = -2729855178402529784L; private static final long serialVersionUID = -2729855178402529784L;
private static final AtomicLong id = new AtomicLong(); private static final AtomicLong id = new AtomicLong();
@ -25,17 +26,20 @@ public class ConcurrentSet<T> extends ConcurrentLinkedQueue2<T> {
private final Node<T> IN_PROGRESS_MARKER = new Node<T>(null); private final Node<T> IN_PROGRESS_MARKER = new Node<T>(null);
private ConcurrentMap<T, Node<T>> entries; private ConcurrentMap<T, Node<T>> entries;
public ConcurrentSet() { public
ConcurrentSet() {
this(16, 0.75f, Runtime.getRuntime().availableProcessors()); this(16, 0.75f, Runtime.getRuntime().availableProcessors());
} }
public ConcurrentSet(int size, float loadFactor, int stripeSize) { public
ConcurrentSet(int size, float loadFactor, int stripeSize) {
super(); super();
this.entries = JavaVersionAdapter.get.concurrentMap(size, loadFactor, 32); this.entries = JavaVersionAdapter.concurrentMap(size, loadFactor, 32);
} }
@Override @Override
public boolean add(T element) { public
boolean add(T element) {
if (element == null) { if (element == null) {
return false; return false;
} }
@ -54,7 +58,8 @@ public class ConcurrentSet<T> extends ConcurrentLinkedQueue2<T> {
} }
@Override @Override
public boolean contains(Object element) { public
boolean contains(Object element) {
if (element == null) { if (element == null) {
return false; return false;
} }
@ -72,12 +77,14 @@ public class ConcurrentSet<T> extends ConcurrentLinkedQueue2<T> {
} }
@Override @Override
public int size() { public
int size() {
return this.entries.size(); return this.entries.size();
} }
@Override @Override
public boolean isEmpty() { public
boolean isEmpty() {
return super.isEmpty(); return super.isEmpty();
} }
@ -85,7 +92,8 @@ public class ConcurrentSet<T> extends ConcurrentLinkedQueue2<T> {
* @return TRUE if the element was successfully removed * @return TRUE if the element was successfully removed
*/ */
@Override @Override
public boolean remove(Object element) { public
boolean remove(Object element) {
while (this.entries.get(element) == this.IN_PROGRESS_MARKER) { while (this.entries.get(element) == this.IN_PROGRESS_MARKER) {
; // data race ; // data race
} }
@ -113,11 +121,13 @@ public class ConcurrentSet<T> extends ConcurrentLinkedQueue2<T> {
} }
@Override @Override
public Iterator<T> iterator() { public
Iterator<T> iterator() {
return new Itr2(); return new Itr2();
} }
private class Itr2 implements Iterator<T> { private
class Itr2 implements Iterator<T> {
/** /**
* Next node to return item for. * Next node to return item for.
*/ */
@ -144,7 +154,8 @@ public class ConcurrentSet<T> extends ConcurrentLinkedQueue2<T> {
* Moves to next valid node and returns item to return for * Moves to next valid node and returns item to return for
* next(), or null if no such. * next(), or null if no such.
*/ */
private T advance() { private
T advance() {
this.lastRet = this.nextNode; // for removing items via iterator this.lastRet = this.nextNode; // for removing items via iterator
T nextItem = this.nextItem; T nextItem = this.nextItem;
@ -152,12 +163,13 @@ public class ConcurrentSet<T> extends ConcurrentLinkedQueue2<T> {
if (this.nextNode == null) { if (this.nextNode == null) {
p = first(); p = first();
pred = null; pred = null;
} else { }
else {
pred = this.nextNode; pred = this.nextNode;
p = succ(this.nextNode); p = succ(this.nextNode);
} }
for (;;) { for (; ; ) {
if (p == null) { if (p == null) {
this.nextNode = null; this.nextNode = null;
this.nextItem = null; this.nextItem = null;
@ -169,7 +181,8 @@ public class ConcurrentSet<T> extends ConcurrentLinkedQueue2<T> {
this.nextNode = p; this.nextNode = p;
this.nextItem = item; this.nextItem = item;
return nextItem; return nextItem;
} else { }
else {
// skip over nulls // skip over nulls
Node<T> next = succ(p); Node<T> next = succ(p);
if (pred != null && next != null) { if (pred != null && next != null) {
@ -183,12 +196,14 @@ public class ConcurrentSet<T> extends ConcurrentLinkedQueue2<T> {
@Override @Override
public boolean hasNext() { public
boolean hasNext() {
return this.nextNode != null; return this.nextNode != null;
} }
@Override @Override
public T next() { public
T next() {
if (this.nextNode == null) { if (this.nextNode == null) {
throw new NoSuchElementException(); throw new NoSuchElementException();
} }
@ -196,7 +211,8 @@ public class ConcurrentSet<T> extends ConcurrentLinkedQueue2<T> {
} }
@Override @Override
public void remove() { public
void remove() {
Node<T> l = this.lastRet; Node<T> l = this.lastRet;
if (l == null) { if (l == null) {
throw new IllegalStateException(); throw new IllegalStateException();
@ -220,37 +236,44 @@ public class ConcurrentSet<T> extends ConcurrentLinkedQueue2<T> {
} }
@Override @Override
public Object[] toArray() { public
Object[] toArray() {
return this.entries.keySet().toArray(); return this.entries.keySet().toArray();
} }
@Override @Override
public <T> T[] toArray(T[] a) { public
<T> T[] toArray(T[] a) {
return this.entries.keySet().toArray(a); return this.entries.keySet().toArray(a);
} }
@Override @Override
public boolean containsAll(Collection<?> c) { public
boolean containsAll(Collection<?> c) {
throw new UnsupportedOperationException("Not implemented"); throw new UnsupportedOperationException("Not implemented");
} }
@Override @Override
public boolean removeAll(Collection<?> c) { public
boolean removeAll(Collection<?> c) {
throw new UnsupportedOperationException("Not implemented"); throw new UnsupportedOperationException("Not implemented");
} }
@Override @Override
public boolean retainAll(Collection<?> c) { public
boolean retainAll(Collection<?> c) {
throw new UnsupportedOperationException("Not implemented"); throw new UnsupportedOperationException("Not implemented");
} }
@Override @Override
public void clear() { public
void clear() {
super.clear(); super.clear();
} }
@Override @Override
public int hashCode() { public
int hashCode() {
final int prime = 31; final int prime = 31;
int result = 1; int result = 1;
result = prime * result + (int) (this.ID ^ this.ID >>> 32); result = prime * result + (int) (this.ID ^ this.ID >>> 32);
@ -258,7 +281,8 @@ public class ConcurrentSet<T> extends ConcurrentLinkedQueue2<T> {
} }
@Override @Override
public boolean equals(Object obj) { public
boolean equals(Object obj) {
if (this == obj) { if (this == obj) {
return true; return true;
} }

View File

@ -10,14 +10,15 @@ import java.util.concurrent.atomic.AtomicInteger;
* @author dorkbox, llc * @author dorkbox, llc
* Date: 2/2/15 * Date: 2/2/15
*/ */
public class NamedThreadFactory implements ThreadFactory { public
class NamedThreadFactory implements ThreadFactory {
/** /**
* The stack size is arbitrary based on JVM implementation. Default is 0 * The 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
* <p> * <p/>
* To be honest, 8k is pretty reasonable for an asynchronous/event based system (32bit) or 16k (64bit) * To be honest, 8k is pretty reasonable for an asynchronous/event based system (32bit) or 16k (64bit)
* Setting the size MAY or MAY NOT have any effect!!! * Setting the size MAY or MAY NOT have any effect!!!
* <p> * <p/>
* Stack size must be specified in bytes. Default is 8k * Stack size must be specified in bytes. Default is 8k
*/ */
private static final long stackSizeForThreads; private static final long stackSizeForThreads;
@ -67,13 +68,15 @@ public class NamedThreadFactory implements ThreadFactory {
private final ThreadGroup group; private final ThreadGroup group;
private final String groupName; private final String groupName;
public NamedThreadFactory(String groupName) { public
NamedThreadFactory(String groupName) {
this.groupName = groupName; this.groupName = groupName;
this.group = new ThreadGroup(groupName); this.group = new ThreadGroup(groupName);
} }
@Override @Override
public Thread newThread(Runnable r) { public
Thread newThread(Runnable r) {
StringBuilder stringBuilder = new StringBuilder(); StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append(this.groupName); stringBuilder.append(this.groupName);
stringBuilder.append('-'); stringBuilder.append('-');
@ -83,7 +86,8 @@ public class NamedThreadFactory implements ThreadFactory {
return newThread(stringBuilder.toString(), r); return newThread(stringBuilder.toString(), r);
} }
public Thread newThread(String name, Runnable r) { public
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
// To be honest, 8k is pretty reasonable for an asynchronous/event based system (32bit) or 16k (64bit) // To be honest, 8k is pretty reasonable for an asynchronous/event based system (32bit) or 16k (64bit)

View File

@ -10,29 +10,37 @@ import com.esotericsoftware.reflectasm.MethodAccess;
* @author dorkbox, llc * @author dorkbox, llc
* Date: 2/2/15 * Date: 2/2/15
*/ */
public class ReflectiveHandlerInvocation implements IHandlerInvocation { public
class ReflectiveHandlerInvocation implements IHandlerInvocation {
public ReflectiveHandlerInvocation() { public
ReflectiveHandlerInvocation() {
super(); super();
} }
@Override @Override
public void invoke(final Object listener, final MethodAccess handler, final int methodIndex, final Object message) throws Throwable { public
void invoke(final Object listener, final MethodAccess handler, final int methodIndex, final Object message) throws Throwable {
handler.invoke(listener, methodIndex, message); handler.invoke(listener, methodIndex, message);
} }
@Override @Override
public void invoke(final Object listener, MethodAccess handler, int methodIndex, final Object message1, final Object message2) throws Throwable { public
void invoke(final Object listener, MethodAccess handler, int methodIndex, final Object message1, final Object message2)
throws Throwable {
handler.invoke(listener, methodIndex, message1, message2); handler.invoke(listener, methodIndex, message1, message2);
} }
@Override @Override
public void invoke(final Object listener, MethodAccess handler, int methodIndex, final Object message1, final Object message2, final Object message3) throws Throwable { public
void invoke(final Object listener, MethodAccess handler, int methodIndex, final Object message1, final Object message2,
final Object message3) throws Throwable {
handler.invoke(listener, methodIndex, message1, message2, message3); handler.invoke(listener, methodIndex, message1, message2, message3);
} }
@Override @Override
public void invoke(final Object listener, MethodAccess handler, int methodIndex, final Object... messages) throws Throwable { public
void invoke(final Object listener, MethodAccess handler, int methodIndex, final Object... messages) throws Throwable {
handler.invoke(listener, methodIndex, messages); handler.invoke(listener, methodIndex, messages);
} }
} }

View File

@ -10,37 +10,45 @@ import com.esotericsoftware.reflectasm.MethodAccess;
* @author dorkbox, llc * @author dorkbox, llc
* Date: 2/2/15 * Date: 2/2/15
*/ */
public class SynchronizedHandlerInvocation implements IHandlerInvocation { public
class SynchronizedHandlerInvocation implements IHandlerInvocation {
private IHandlerInvocation delegate; private IHandlerInvocation delegate;
public SynchronizedHandlerInvocation(IHandlerInvocation delegate) { public
SynchronizedHandlerInvocation(IHandlerInvocation delegate) {
this.delegate = delegate; this.delegate = delegate;
} }
@Override @Override
public void invoke(final Object listener, final MethodAccess handler, final int methodIndex, final Object message) throws Throwable { public
void invoke(final Object listener, final MethodAccess handler, final int methodIndex, final Object message) throws Throwable {
synchronized (listener) { synchronized (listener) {
this.delegate.invoke(listener, handler, methodIndex, message); this.delegate.invoke(listener, handler, methodIndex, message);
} }
} }
@Override @Override
public void invoke(final Object listener, MethodAccess handler, int methodIndex, final Object message1, final Object message2) throws Throwable { public
void invoke(final Object listener, MethodAccess handler, int methodIndex, final Object message1, final Object message2)
throws Throwable {
synchronized (listener) { synchronized (listener) {
this.delegate.invoke(listener, handler, methodIndex, message1, message2); this.delegate.invoke(listener, handler, methodIndex, message1, message2);
} }
} }
@Override @Override
public void invoke(final Object listener, MethodAccess handler, int methodIndex, final Object message1, final Object message2, final Object message3) throws Throwable { public
void invoke(final Object listener, MethodAccess handler, int methodIndex, final Object message1, final Object message2,
final Object message3) throws Throwable {
synchronized (listener) { synchronized (listener) {
this.delegate.invoke(listener, handler, methodIndex, message1, message2, message3); this.delegate.invoke(listener, handler, methodIndex, message1, message2, message3);
} }
} }
@Override @Override
public void invoke(final Object listener, MethodAccess handler, int methodIndex, final Object... messages) throws Throwable { public
void invoke(final Object listener, MethodAccess handler, int methodIndex, final Object... messages) throws Throwable {
synchronized (listener) { synchronized (listener) {
this.delegate.invoke(listener, handler, methodIndex, messages); this.delegate.invoke(listener, handler, methodIndex, messages);
} }

View File

@ -6,28 +6,33 @@ import java.util.Collection;
/** /**
* *
*/ */
public class DefaultErrorHandler implements ErrorHandlingSupport { public
class DefaultErrorHandler implements ErrorHandlingSupport {
private static final String ERROR_HANDLER_MSG = "INFO: No error handler has been configured to handle exceptions during publication.\n" + private static final String ERROR_HANDLER_MSG =
"Publication error handlers can be added by bus.getErrorHandler().addErrorHandler()\n" + "INFO: No error handler has been configured to handle exceptions during publication.\n" +
"Falling back to console logger."; "Publication error handlers can be added by bus.getErrorHandler().addErrorHandler()\n" +
"Falling back to console logger.";
// this handler will receive all errors that occur during message dispatch or message handling // this handler will receive all errors that occur during message dispatch or message handling
private final Collection<IPublicationErrorHandler> errorHandlers = new ArrayDeque<IPublicationErrorHandler>(); private final Collection<IPublicationErrorHandler> errorHandlers = new ArrayDeque<IPublicationErrorHandler>();
public DefaultErrorHandler() { public
DefaultErrorHandler() {
} }
@Override @Override
public final void addErrorHandler(IPublicationErrorHandler handler) { public final
void addErrorHandler(IPublicationErrorHandler handler) {
synchronized (this.errorHandlers) { synchronized (this.errorHandlers) {
this.errorHandlers.add(handler); this.errorHandlers.add(handler);
} }
} }
@Override @Override
public final void handlePublicationError(PublicationError error) { public final
void handlePublicationError(PublicationError error) {
synchronized (this.errorHandlers) { synchronized (this.errorHandlers) {
for (IPublicationErrorHandler errorHandler : this.errorHandlers) { for (IPublicationErrorHandler errorHandler : this.errorHandlers) {
errorHandler.handleError(error); errorHandler.handleError(error);
@ -36,7 +41,8 @@ public class DefaultErrorHandler implements ErrorHandlingSupport {
} }
@Override @Override
public void handleError(final String error, final Class<?> listenerClass) { public
void handleError(final String error, final Class<?> listenerClass) {
synchronized (this.errorHandlers) { synchronized (this.errorHandlers) {
for (IPublicationErrorHandler errorHandler : this.errorHandlers) { for (IPublicationErrorHandler errorHandler : this.errorHandlers) {
errorHandler.handleError(error, listenerClass); errorHandler.handleError(error, listenerClass);
@ -45,7 +51,8 @@ public class DefaultErrorHandler implements ErrorHandlingSupport {
} }
@Override @Override
public void start() { public
void start() {
synchronized (this.errorHandlers) { synchronized (this.errorHandlers) {
if (this.errorHandlers.isEmpty()) { if (this.errorHandlers.isEmpty()) {
this.errorHandlers.add(new IPublicationErrorHandler.ConsoleLogger()); this.errorHandlers.add(new IPublicationErrorHandler.ConsoleLogger());

View File

@ -5,7 +5,8 @@ package dorkbox.util.messagebus.error;
* @author dorkbox, llc * @author dorkbox, llc
* Date: 2/2/15 * Date: 2/2/15
*/ */
public interface ErrorHandlingSupport { public
interface ErrorHandlingSupport {
/** /**
* Publication errors may occur at various points of time during message delivery. A handler may throw an exception, * Publication errors may occur at various points of time during message delivery. A handler may throw an exception,

View File

@ -5,12 +5,13 @@ package dorkbox.util.messagebus.error;
* error occurs during message publication. * error occurs during message publication.
* 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 lead to failures during the message publication process. * of a security manager or other reasons might lead to failures during the message publication process.
* <p> * <p/>
* *
* @author bennidi * @author bennidi
* Date: 2/22/12 * Date: 2/22/12
*/ */
public interface IPublicationErrorHandler { public
interface IPublicationErrorHandler {
/** /**
* Handle the given publication error. * Handle the given publication error.
@ -22,7 +23,7 @@ public 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
*/ */
void handleError(String error, final Class<?> listenerClass); void handleError(String error, final Class<?> listenerClass);
@ -32,12 +33,14 @@ public interface IPublicationErrorHandler {
* 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 class ConsoleLogger implements IPublicationErrorHandler { final
class ConsoleLogger implements IPublicationErrorHandler {
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
@Override @Override
public void handleError(final PublicationError error) { public
void handleError(final PublicationError error) {
// Printout the error itself // Printout the error itself
System.out.println(error); System.out.println(error);
@ -51,7 +54,8 @@ public interface IPublicationErrorHandler {
* {@inheritDoc} * {@inheritDoc}
*/ */
@Override @Override
public void handleError(final String error, final Class<?> listenerClass) { public
void handleError(final String error, final Class<?> listenerClass) {
// Printout the error itself // Printout the error itself
System.out.println(new StringBuilder().append(error).append(": ").append(listenerClass.getSimpleName()).toString()); System.out.println(new StringBuilder().append(error).append(": ").append(listenerClass.getSimpleName()).toString());
} }

View File

@ -6,21 +6,26 @@ package dorkbox.util.messagebus.error;
* @author bennidi * @author bennidi
* Date: 3/29/13 * Date: 3/29/13
*/ */
public class MessageBusException extends Exception { public
class MessageBusException extends Exception {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
public MessageBusException() { public
MessageBusException() {
} }
public MessageBusException(String message) { public
MessageBusException(String message) {
super(message); super(message);
} }
public MessageBusException(String message, Throwable cause) { public
MessageBusException(String message, Throwable cause) {
super(message, cause); super(message, cause);
} }
public MessageBusException(Throwable cause) { public
MessageBusException(Throwable cause) {
super(cause); super(cause);
} }
} }

View File

@ -14,7 +14,8 @@ import java.util.Arrays;
* @author dorkbox, llc * @author dorkbox, llc
* Date: 2/2/15 * Date: 2/2/15
*/ */
public class PublicationError { public
class PublicationError {
// Internal state // Internal state
private Throwable cause; private Throwable cause;
@ -25,14 +26,16 @@ public class PublicationError {
/** /**
* Default constructor. * Default constructor.
*/ */
public PublicationError() { public
PublicationError() {
super(); super();
} }
/** /**
* @return The Throwable giving rise to this PublicationError. * @return The Throwable giving rise to this PublicationError.
*/ */
public Throwable getCause() { public
Throwable getCause() {
return this.cause; return this.cause;
} }
@ -42,32 +45,38 @@ public class PublicationError {
* @param cause A Throwable which gave rise to this PublicationError. * @param cause A Throwable which gave rise to this PublicationError.
* @return This PublicationError. * @return This PublicationError.
*/ */
public PublicationError setCause(Throwable cause) { public
PublicationError setCause(Throwable cause) {
this.cause = cause; this.cause = cause;
return this; return this;
} }
public String getMessage() { public
String getMessage() {
return this.message; return this.message;
} }
public PublicationError setMessage(String message) { public
PublicationError setMessage(String message) {
this.message = message; this.message = message;
return this; return this;
} }
public Object[] getPublishedObject() { public
Object[] getPublishedObject() {
return this.publishedObjects; return this.publishedObjects;
} }
public PublicationError setPublishedObject(Object publishedObject) { public
PublicationError setPublishedObject(Object publishedObject) {
this.publishedObjects = new Object[1]; this.publishedObjects = new Object[1];
this.publishedObjects[0] = publishedObject; this.publishedObjects[0] = publishedObject;
return this; return this;
} }
public PublicationError setPublishedObject(Object publishedObject1, Object publishedObject2) { public
PublicationError setPublishedObject(Object publishedObject1, Object publishedObject2) {
this.publishedObjects = new Object[2]; this.publishedObjects = new Object[2];
this.publishedObjects[0] = publishedObject1; this.publishedObjects[0] = publishedObject1;
this.publishedObjects[1] = publishedObject2; this.publishedObjects[1] = publishedObject2;
@ -75,7 +84,8 @@ public class PublicationError {
return this; return this;
} }
public PublicationError setPublishedObject(Object publishedObject1, Object publishedObject2, Object publishedObject3) { public
PublicationError setPublishedObject(Object publishedObject1, Object publishedObject2, Object publishedObject3) {
this.publishedObjects = new Object[3]; this.publishedObjects = new Object[3];
this.publishedObjects[0] = publishedObject1; this.publishedObjects[0] = publishedObject1;
this.publishedObjects[1] = publishedObject2; this.publishedObjects[1] = publishedObject2;
@ -88,15 +98,16 @@ public class PublicationError {
* {@inheritDoc} * {@inheritDoc}
*/ */
@Override @Override
public String toString() { public
String toString() {
String newLine = System.getProperty("line.separator"); String newLine = System.getProperty("line.separator");
return "PublicationError{" + return "PublicationError{" +
newLine + newLine +
"\tcause=" + this.cause + "\tcause=" + this.cause +
newLine + newLine +
"\tmessage='" + this.message + '\'' + "\tmessage='" + this.message + '\'' +
newLine + newLine +
"\tpublishedObject=" + Arrays.deepToString(this.publishedObjects) + "\tpublishedObject=" + Arrays.deepToString(this.publishedObjects) +
'}'; '}';
} }
} }

View File

@ -11,7 +11,8 @@ import dorkbox.util.messagebus.utils.VarArgUtils;
import java.lang.reflect.Array; import java.lang.reflect.Array;
import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicBoolean;
public class PublisherAll_MultiArg implements Publisher { public
class PublisherAll_MultiArg implements Publisher {
private final ErrorHandlingSupport errorHandler; private final ErrorHandlingSupport errorHandler;
private final Subscriber subscriber; private final Subscriber subscriber;
@ -20,7 +21,8 @@ public class PublisherAll_MultiArg implements Publisher {
private final AtomicBoolean varArgPossibility; private final AtomicBoolean varArgPossibility;
final VarArgUtils varArgUtils; final VarArgUtils varArgUtils;
public PublisherAll_MultiArg(final ErrorHandlingSupport errorHandler, final Subscriber subscriber, final StampedLock lock) { public
PublisherAll_MultiArg(final ErrorHandlingSupport errorHandler, final Subscriber subscriber, final StampedLock lock) {
this.errorHandler = errorHandler; this.errorHandler = errorHandler;
this.subscriber = subscriber; this.subscriber = subscriber;
this.lock = lock; this.lock = lock;
@ -30,7 +32,8 @@ public class PublisherAll_MultiArg implements Publisher {
} }
@Override @Override
public void publish(final Object message1) { public
void publish(final Object message1) {
try { try {
final Class<?> messageClass = message1.getClass(); final Class<?> messageClass = message1.getClass();
final boolean isArray = messageClass.isArray(); final boolean isArray = messageClass.isArray();
@ -117,13 +120,14 @@ public class PublisherAll_MultiArg implements Publisher {
} }
} }
} catch (Throwable e) { } catch (Throwable e) {
errorHandler.handlePublicationError(new PublicationError().setMessage("Error during invocation of message handler.").setCause(e) errorHandler.handlePublicationError(new PublicationError().setMessage("Error during invocation of message handler.").setCause(
.setPublishedObject(message1)); e).setPublishedObject(message1));
} }
} }
@Override @Override
public void publish(final Object message1, final Object message2) { public
void publish(final Object message1, final Object message2) {
try { try {
final Class<?> messageClass1 = message1.getClass(); final Class<?> messageClass1 = message1.getClass();
final Class<?> messageClass2 = message2.getClass(); final Class<?> messageClass2 = message2.getClass();
@ -215,13 +219,14 @@ public class PublisherAll_MultiArg implements Publisher {
} }
} }
} catch (Throwable e) { } catch (Throwable e) {
errorHandler.handlePublicationError(new PublicationError().setMessage("Error during invocation of message handler.").setCause(e) errorHandler.handlePublicationError(new PublicationError().setMessage("Error during invocation of message handler.").setCause(
.setPublishedObject(message1, message2)); e).setPublishedObject(message1, message2));
} }
} }
@Override @Override
public void publish(final Object message1, final Object message2, final Object message3) { public
void publish(final Object message1, final Object message2, final Object message3) {
try { try {
final Class<?> messageClass1 = message1.getClass(); final Class<?> messageClass1 = message1.getClass();
final Class<?> messageClass2 = message2.getClass(); final Class<?> messageClass2 = message2.getClass();
@ -319,13 +324,14 @@ public class PublisherAll_MultiArg implements Publisher {
} }
} }
} catch (Throwable e) { } catch (Throwable e) {
errorHandler.handlePublicationError(new PublicationError().setMessage("Error during invocation of message handler.").setCause(e) errorHandler.handlePublicationError(new PublicationError().setMessage("Error during invocation of message handler.").setCause(
.setPublishedObject(message1, message2, message3)); e).setPublishedObject(message1, message2, message3));
} }
} }
@Override @Override
public void publish(final Object[] messages) { public
void publish(final Object[] messages) {
publish((Object) messages); publish((Object) messages);
} }
} }

View File

@ -9,20 +9,22 @@ import dorkbox.util.messagebus.subscription.Subscription;
import java.util.Arrays; import java.util.Arrays;
public class PublisherExactWithSuperTypes_FirstArg implements Publisher { public
class PublisherExactWithSuperTypes_FirstArg implements Publisher {
private final ErrorHandlingSupport errorHandler; private final ErrorHandlingSupport errorHandler;
private final Subscriber subscriber; private final Subscriber subscriber;
private final StampedLock lock; private final StampedLock lock;
public PublisherExactWithSuperTypes_FirstArg(final ErrorHandlingSupport errorHandler, final Subscriber subscriber, public
final StampedLock lock) { PublisherExactWithSuperTypes_FirstArg(final ErrorHandlingSupport errorHandler, final Subscriber subscriber, final StampedLock lock) {
this.errorHandler = errorHandler; this.errorHandler = errorHandler;
this.subscriber = subscriber; this.subscriber = subscriber;
this.lock = lock; this.lock = lock;
} }
@Override @Override
public void publish(final Object message1) { public
void publish(final Object message1) {
try { try {
final Class<?> messageClass = message1.getClass(); final Class<?> messageClass = message1.getClass();
@ -61,13 +63,14 @@ public class PublisherExactWithSuperTypes_FirstArg implements Publisher {
} }
} }
} catch (Throwable e) { } catch (Throwable e) {
errorHandler.handlePublicationError(new PublicationError().setMessage("Error during invocation of message handler.").setCause(e) errorHandler.handlePublicationError(new PublicationError().setMessage("Error during invocation of message handler.").setCause(
.setPublishedObject(message1)); e).setPublishedObject(message1));
} }
} }
@Override @Override
public void publish(final Object message1, final Object message2) { public
void publish(final Object message1, final Object message2) {
try { try {
final Class<?> messageClass = message1.getClass(); final Class<?> messageClass = message1.getClass();
@ -106,13 +109,14 @@ public class PublisherExactWithSuperTypes_FirstArg implements Publisher {
} }
} }
} catch (Throwable e) { } catch (Throwable e) {
errorHandler.handlePublicationError(new PublicationError().setMessage("Error during invocation of message handler.").setCause(e) errorHandler.handlePublicationError(new PublicationError().setMessage("Error during invocation of message handler.").setCause(
.setPublishedObject(message1, message2)); e).setPublishedObject(message1, message2));
} }
} }
@Override @Override
public void publish(final Object message1, final Object message2, final Object message3) { public
void publish(final Object message1, final Object message2, final Object message3) {
try { try {
final Class<?> messageClass = message1.getClass(); final Class<?> messageClass = message1.getClass();
@ -151,13 +155,14 @@ public class PublisherExactWithSuperTypes_FirstArg implements Publisher {
} }
} }
} catch (Throwable e) { } catch (Throwable e) {
errorHandler.handlePublicationError(new PublicationError().setMessage("Error during invocation of message handler.").setCause(e) errorHandler.handlePublicationError(new PublicationError().setMessage("Error during invocation of message handler.").setCause(
.setPublishedObject(message1, message2, message3)); e).setPublishedObject(message1, message2, message3));
} }
} }
@Override @Override
public void publish(final Object[] messages) { public
void publish(final Object[] messages) {
try { try {
final Object message1 = messages[0]; final Object message1 = messages[0];
final Class<?> messageClass = message1.getClass(); final Class<?> messageClass = message1.getClass();
@ -199,8 +204,8 @@ public class PublisherExactWithSuperTypes_FirstArg implements Publisher {
} }
} }
} catch (Throwable e) { } catch (Throwable e) {
errorHandler.handlePublicationError(new PublicationError().setMessage("Error during invocation of message handler.").setCause(e) errorHandler.handlePublicationError(new PublicationError().setMessage("Error during invocation of message handler.").setCause(
.setPublishedObject(messages)); e).setPublishedObject(messages));
} }
} }
} }

View File

@ -7,20 +7,22 @@ import dorkbox.util.messagebus.error.PublicationError;
import dorkbox.util.messagebus.subscription.Subscriber; import dorkbox.util.messagebus.subscription.Subscriber;
import dorkbox.util.messagebus.subscription.Subscription; import dorkbox.util.messagebus.subscription.Subscription;
public class PublisherExactWithSuperTypes_MultiArg implements Publisher { public
class PublisherExactWithSuperTypes_MultiArg implements Publisher {
private final ErrorHandlingSupport errorHandler; private final ErrorHandlingSupport errorHandler;
private final Subscriber subscriber; private final Subscriber subscriber;
private final StampedLock lock; private final StampedLock lock;
public PublisherExactWithSuperTypes_MultiArg(final ErrorHandlingSupport errorHandler, final Subscriber subscriber, public
final StampedLock lock) { PublisherExactWithSuperTypes_MultiArg(final ErrorHandlingSupport errorHandler, final Subscriber subscriber, final StampedLock lock) {
this.errorHandler = errorHandler; this.errorHandler = errorHandler;
this.subscriber = subscriber; this.subscriber = subscriber;
this.lock = lock; this.lock = lock;
} }
@Override @Override
public void publish(final Object message1) { public
void publish(final Object message1) {
try { try {
final Class<?> messageClass = message1.getClass(); final Class<?> messageClass = message1.getClass();
@ -54,13 +56,14 @@ public class PublisherExactWithSuperTypes_MultiArg implements Publisher {
} }
} }
} catch (Throwable e) { } catch (Throwable e) {
errorHandler.handlePublicationError(new PublicationError().setMessage("Error during invocation of message handler.").setCause(e) errorHandler.handlePublicationError(new PublicationError().setMessage("Error during invocation of message handler.").setCause(
.setPublishedObject(message1)); e).setPublishedObject(message1));
} }
} }
@Override @Override
public void publish(final Object message1, final Object message2) { public
void publish(final Object message1, final Object message2) {
try { try {
final Class<?> messageClass1 = message1.getClass(); final Class<?> messageClass1 = message1.getClass();
final Class<?> messageClass2 = message2.getClass(); final Class<?> messageClass2 = message2.getClass();
@ -95,13 +98,14 @@ public class PublisherExactWithSuperTypes_MultiArg implements Publisher {
} }
} }
} catch (Throwable e) { } catch (Throwable e) {
errorHandler.handlePublicationError(new PublicationError().setMessage("Error during invocation of message handler.").setCause(e) errorHandler.handlePublicationError(new PublicationError().setMessage("Error during invocation of message handler.").setCause(
.setPublishedObject(message1, message2)); e).setPublishedObject(message1, message2));
} }
} }
@Override @Override
public void publish(final Object message1, final Object message2, final Object message3) { public
void publish(final Object message1, final Object message2, final Object message3) {
try { try {
final Class<?> messageClass1 = message1.getClass(); final Class<?> messageClass1 = message1.getClass();
final Class<?> messageClass2 = message2.getClass(); final Class<?> messageClass2 = message2.getClass();
@ -110,7 +114,8 @@ public class PublisherExactWithSuperTypes_MultiArg implements Publisher {
final StampedLock lock = this.lock; final StampedLock lock = this.lock;
long stamp = lock.readLock(); long stamp = lock.readLock();
final Subscription[] subscriptions = subscriber.getExactAndSuper(messageClass1, messageClass2, messageClass3); // can return null final Subscription[] subscriptions = subscriber.getExactAndSuper(messageClass1, messageClass2,
messageClass3); // can return null
lock.unlockRead(stamp); lock.unlockRead(stamp);
// Run subscriptions // Run subscriptions
@ -138,13 +143,14 @@ public class PublisherExactWithSuperTypes_MultiArg implements Publisher {
} }
} }
} catch (Throwable e) { } catch (Throwable e) {
errorHandler.handlePublicationError(new PublicationError().setMessage("Error during invocation of message handler.").setCause(e) errorHandler.handlePublicationError(new PublicationError().setMessage("Error during invocation of message handler.").setCause(
.setPublishedObject(message1, message2, message3)); e).setPublishedObject(message1, message2, message3));
} }
} }
@Override @Override
public void publish(final Object[] messages) { public
void publish(final Object[] messages) {
publish((Object) messages); publish((Object) messages);
} }
} }

View File

@ -7,19 +7,22 @@ import dorkbox.util.messagebus.error.PublicationError;
import dorkbox.util.messagebus.subscription.Subscriber; import dorkbox.util.messagebus.subscription.Subscriber;
import dorkbox.util.messagebus.subscription.Subscription; import dorkbox.util.messagebus.subscription.Subscription;
public class PublisherExact_FirstArg implements Publisher { public
class PublisherExact_FirstArg implements Publisher {
private final ErrorHandlingSupport errorHandler; private final ErrorHandlingSupport errorHandler;
private final Subscriber subscriber; private final Subscriber subscriber;
private final StampedLock lock; private final StampedLock lock;
public PublisherExact_FirstArg(final ErrorHandlingSupport errorHandler, final Subscriber subscriber, final StampedLock lock) { public
PublisherExact_FirstArg(final ErrorHandlingSupport errorHandler, final Subscriber subscriber, final StampedLock lock) {
this.errorHandler = errorHandler; this.errorHandler = errorHandler;
this.subscriber = subscriber; this.subscriber = subscriber;
this.lock = lock; this.lock = lock;
} }
@Override @Override
public void publish(final Object message1) { public
void publish(final Object message1) {
try { try {
final Class<?> messageClass = message1.getClass(); final Class<?> messageClass = message1.getClass();
@ -58,13 +61,14 @@ public class PublisherExact_FirstArg implements Publisher {
} }
} }
} catch (Throwable e) { } catch (Throwable e) {
errorHandler.handlePublicationError(new PublicationError().setMessage("Error during invocation of message handler.").setCause(e) errorHandler.handlePublicationError(new PublicationError().setMessage("Error during invocation of message handler.").setCause(
.setPublishedObject(message1)); e).setPublishedObject(message1));
} }
} }
@Override @Override
public void publish(final Object message1, final Object message2) { public
void publish(final Object message1, final Object message2) {
try { try {
final Class<?> messageClass = message1.getClass(); final Class<?> messageClass = message1.getClass();
@ -103,13 +107,14 @@ public class PublisherExact_FirstArg implements Publisher {
} }
} }
} catch (Throwable e) { } catch (Throwable e) {
errorHandler.handlePublicationError(new PublicationError().setMessage("Error during invocation of message handler.").setCause(e) errorHandler.handlePublicationError(new PublicationError().setMessage("Error during invocation of message handler.").setCause(
.setPublishedObject(message1, message2)); e).setPublishedObject(message1, message2));
} }
} }
@Override @Override
public void publish(final Object message1, final Object message2, final Object message3) { public
void publish(final Object message1, final Object message2, final Object message3) {
try { try {
final Class<?> messageClass = message1.getClass(); final Class<?> messageClass = message1.getClass();
@ -148,13 +153,14 @@ public class PublisherExact_FirstArg implements Publisher {
} }
} }
} catch (Throwable e) { } catch (Throwable e) {
errorHandler.handlePublicationError(new PublicationError().setMessage("Error during invocation of message handler.").setCause(e) errorHandler.handlePublicationError(new PublicationError().setMessage("Error during invocation of message handler.").setCause(
.setPublishedObject(message1, message2, message3)); e).setPublishedObject(message1, message2, message3));
} }
} }
@Override @Override
public void publish(final Object[] messages) { public
void publish(final Object[] messages) {
try { try {
final Class<?> messageClass = messages[0].getClass(); final Class<?> messageClass = messages[0].getClass();
final int length = messages.length; final int length = messages.length;
@ -194,8 +200,8 @@ public class PublisherExact_FirstArg implements Publisher {
} }
} }
} catch (Throwable e) { } catch (Throwable e) {
errorHandler.handlePublicationError(new PublicationError().setMessage("Error during invocation of message handler.").setCause(e) errorHandler.handlePublicationError(new PublicationError().setMessage("Error during invocation of message handler.").setCause(
.setPublishedObject(messages)); e).setPublishedObject(messages));
} }
} }
} }

View File

@ -7,19 +7,22 @@ import dorkbox.util.messagebus.error.PublicationError;
import dorkbox.util.messagebus.subscription.Subscriber; import dorkbox.util.messagebus.subscription.Subscriber;
import dorkbox.util.messagebus.subscription.Subscription; import dorkbox.util.messagebus.subscription.Subscription;
public class PublisherExact_MultiArg implements Publisher { public
class PublisherExact_MultiArg implements Publisher {
private final ErrorHandlingSupport errorHandler; private final ErrorHandlingSupport errorHandler;
private final Subscriber subscriber; private final Subscriber subscriber;
private final StampedLock lock; private final StampedLock lock;
public PublisherExact_MultiArg(final ErrorHandlingSupport errorHandler, final Subscriber subscriber, final StampedLock lock) { public
PublisherExact_MultiArg(final ErrorHandlingSupport errorHandler, final Subscriber subscriber, final StampedLock lock) {
this.errorHandler = errorHandler; this.errorHandler = errorHandler;
this.subscriber = subscriber; this.subscriber = subscriber;
this.lock = lock; this.lock = lock;
} }
@Override @Override
public void publish(final Object message1) { public
void publish(final Object message1) {
try { try {
final Class<?> messageClass = message1.getClass(); final Class<?> messageClass = message1.getClass();
@ -53,13 +56,14 @@ public class PublisherExact_MultiArg implements Publisher {
} }
} }
} catch (Throwable e) { } catch (Throwable e) {
errorHandler.handlePublicationError(new PublicationError().setMessage("Error during invocation of message handler.").setCause(e) errorHandler.handlePublicationError(new PublicationError().setMessage("Error during invocation of message handler.").setCause(
.setPublishedObject(message1)); e).setPublishedObject(message1));
} }
} }
@Override @Override
public void publish(final Object message1, final Object message2) { public
void publish(final Object message1, final Object message2) {
try { try {
final Class<?> messageClass1 = message1.getClass(); final Class<?> messageClass1 = message1.getClass();
final Class<?> messageClass2 = message2.getClass(); final Class<?> messageClass2 = message2.getClass();
@ -94,13 +98,14 @@ public class PublisherExact_MultiArg implements Publisher {
} }
} }
} catch (Throwable e) { } catch (Throwable e) {
errorHandler.handlePublicationError(new PublicationError().setMessage("Error during invocation of message handler.").setCause(e) errorHandler.handlePublicationError(new PublicationError().setMessage("Error during invocation of message handler.").setCause(
.setPublishedObject(message1, message2)); e).setPublishedObject(message1, message2));
} }
} }
@Override @Override
public void publish(final Object message1, final Object message2, final Object message3) { public
void publish(final Object message1, final Object message2, final Object message3) {
try { try {
final Class<?> messageClass1 = message1.getClass(); final Class<?> messageClass1 = message1.getClass();
final Class<?> messageClass2 = message2.getClass(); final Class<?> messageClass2 = message2.getClass();
@ -136,13 +141,14 @@ public class PublisherExact_MultiArg implements Publisher {
} }
} }
} catch (Throwable e) { } catch (Throwable e) {
errorHandler.handlePublicationError(new PublicationError().setMessage("Error during invocation of message handler.").setCause(e) errorHandler.handlePublicationError(new PublicationError().setMessage("Error during invocation of message handler.").setCause(
.setPublishedObject(message1, message2, message3)); e).setPublishedObject(message1, message2, message3));
} }
} }
@Override @Override
public void publish(final Object[] messages) { public
void publish(final Object[] messages) {
publish((Object) messages); publish((Object) messages);
} }
} }

View File

@ -33,7 +33,7 @@ public class FirstArgSubscriber implements Subscriber {
this.errorHandler = errorHandler; this.errorHandler = errorHandler;
// the following are used ONLY for FIRST ARG subscription/publication. (subscriptionsPerMessageMulti isn't used in this case) // the following are used ONLY for FIRST ARG subscription/publication. (subscriptionsPerMessageMulti isn't used in this case)
this.subscriptionsPerMessage = JavaVersionAdapter.get.concurrentMap(32, LOAD_FACTOR, 1); this.subscriptionsPerMessage = JavaVersionAdapter.concurrentMap(32, LOAD_FACTOR, 1);
} }
// inside a write lock // inside a write lock

View File

@ -15,7 +15,8 @@ import java.util.concurrent.atomic.AtomicBoolean;
/** /**
* Permits subscriptions with a varying length of parameters as the signature, which must be match by the publisher for it to be accepted * Permits subscriptions with a varying length of parameters as the signature, which must be match by the publisher for it to be accepted
*/ */
public class MultiArgSubscriber implements Subscriber { public
class MultiArgSubscriber implements Subscriber {
private final ErrorHandlingSupport errorHandler; private final ErrorHandlingSupport errorHandler;
@ -31,10 +32,11 @@ public class MultiArgSubscriber implements Subscriber {
// shortcut publication if we know there is no possibility of varArg (ie: a method that has an array as arguments) // shortcut publication if we know there is no possibility of varArg (ie: a method that has an array as arguments)
private final AtomicBoolean varArgPossibility = new AtomicBoolean(false); private final AtomicBoolean varArgPossibility = new AtomicBoolean(false);
public MultiArgSubscriber(final ErrorHandlingSupport errorHandler, final ClassUtils classUtils) { public
MultiArgSubscriber(final ErrorHandlingSupport errorHandler, final ClassUtils classUtils) {
this.errorHandler = errorHandler; this.errorHandler = errorHandler;
this.subscriptionsPerMessageSingle = JavaVersionAdapter.get.concurrentMap(32, LOAD_FACTOR, 1); this.subscriptionsPerMessageSingle = JavaVersionAdapter.concurrentMap(32, LOAD_FACTOR, 1);
this.subscriptionsPerMessageMulti = new HashMapTree<Class<?>, ArrayList<Subscription>>(4, LOAD_FACTOR); this.subscriptionsPerMessageMulti = new HashMapTree<Class<?>, ArrayList<Subscription>>(4, LOAD_FACTOR);
this.subUtils = new SubscriptionUtils(classUtils, Subscriber.LOAD_FACTOR); this.subUtils = new SubscriptionUtils(classUtils, Subscriber.LOAD_FACTOR);
@ -45,17 +47,20 @@ public class MultiArgSubscriber implements Subscriber {
} }
@Override @Override
public AtomicBoolean getVarArgPossibility() { public
AtomicBoolean getVarArgPossibility() {
return varArgPossibility; return varArgPossibility;
} }
@Override @Override
public VarArgUtils getVarArgUtils() { public
VarArgUtils getVarArgUtils() {
return varArgUtils; return varArgUtils;
} }
@Override @Override
public void clear() { public
void clear() {
this.subUtils.clear(); this.subUtils.clear();
this.varArgUtils.clear(); this.varArgUtils.clear();
} }
@ -63,10 +68,10 @@ public class MultiArgSubscriber implements Subscriber {
// inside a write lock // inside a write lock
// add this subscription to each of the handled types // add this subscription to each of the handled types
// to activate this sub for publication // to activate this sub for publication
private void registerMulti(final Subscription subscription, final Class<?> listenerClass, private
final Map<Class<?>, ArrayList<Subscription>> subsPerMessageSingle, void registerMulti(final Subscription subscription, final Class<?> listenerClass,
final HashMapTree<Class<?>, ArrayList<Subscription>> subsPerMessageMulti, final Map<Class<?>, ArrayList<Subscription>> subsPerMessageSingle,
final AtomicBoolean varArgPossibility) { final HashMapTree<Class<?>, ArrayList<Subscription>> subsPerMessageMulti, final AtomicBoolean varArgPossibility) {
final MessageHandler handler = subscription.getHandler(); final MessageHandler handler = subscription.getHandler();
final Class<?>[] messageHandlerTypes = handler.getHandledMessages(); final Class<?>[] messageHandlerTypes = handler.getHandledMessages();
@ -131,7 +136,8 @@ public class MultiArgSubscriber implements Subscriber {
} }
@Override @Override
public void register(final Class<?> listenerClass, final int handlersSize, final Subscription[] subsPerListener) { public
void register(final Class<?> listenerClass, final int handlersSize, final Subscription[] subsPerListener) {
final Map<Class<?>, ArrayList<Subscription>> subsPerMessageSingle = this.subscriptionsPerMessageSingle; final Map<Class<?>, ArrayList<Subscription>> subsPerMessageSingle = this.subscriptionsPerMessageSingle;
final HashMapTree<Class<?>, ArrayList<Subscription>> subsPerMessageMulti = this.subscriptionsPerMessageMulti; final HashMapTree<Class<?>, ArrayList<Subscription>> subsPerMessageMulti = this.subscriptionsPerMessageMulti;
@ -149,7 +155,8 @@ public class MultiArgSubscriber implements Subscriber {
} }
@Override @Override
public void shutdown() { public
void shutdown() {
this.subscriptionsPerMessageSingle.clear(); this.subscriptionsPerMessageSingle.clear();
this.subscriptionsPerMessageMulti.clear(); this.subscriptionsPerMessageMulti.clear();
@ -157,24 +164,27 @@ public class MultiArgSubscriber implements Subscriber {
} }
@Override @Override
public ArrayList<Subscription> getExactAsArray(final Class<?> messageClass) { public
ArrayList<Subscription> getExactAsArray(final Class<?> messageClass) {
return subscriptionsPerMessageSingle.get(messageClass); return subscriptionsPerMessageSingle.get(messageClass);
} }
@Override @Override
public ArrayList<Subscription> getExactAsArray(final Class<?> messageClass1, final Class<?> messageClass2) { public
ArrayList<Subscription> getExactAsArray(final Class<?> messageClass1, final Class<?> messageClass2) {
return subscriptionsPerMessageMulti.get(messageClass1, messageClass2); return subscriptionsPerMessageMulti.get(messageClass1, messageClass2);
} }
@Override @Override
public ArrayList<Subscription> getExactAsArray(final Class<?> messageClass1, final Class<?> messageClass2, public
final Class<?> messageClass3) { ArrayList<Subscription> getExactAsArray(final Class<?> messageClass1, final Class<?> messageClass2, final Class<?> messageClass3) {
return subscriptionsPerMessageMulti.get(messageClass1, messageClass2, messageClass3); return subscriptionsPerMessageMulti.get(messageClass1, messageClass2, messageClass3);
} }
// can return null // can return null
@Override @Override
public Subscription[] getExactAndSuper(final Class<?> messageClass) { public
Subscription[] getExactAndSuper(final Class<?> messageClass) {
ArrayList<Subscription> collection = getExactAsArray(messageClass); // can return null ArrayList<Subscription> collection = getExactAsArray(messageClass); // can return null
// now publish superClasses // now publish superClasses
@ -203,7 +213,8 @@ public class MultiArgSubscriber implements Subscriber {
// can return null // can return null
@Override @Override
public Subscription[] getExact(final Class<?> messageClass) { public
Subscription[] getExact(final Class<?> messageClass) {
final ArrayList<Subscription> collection = getExactAsArray(messageClass); final ArrayList<Subscription> collection = getExactAsArray(messageClass);
if (collection != null) { if (collection != null) {
@ -218,7 +229,8 @@ public class MultiArgSubscriber implements Subscriber {
// can return null // can return null
@Override @Override
public Subscription[] getExact(final Class<?> messageClass1, final Class<?> messageClass2) { public
Subscription[] getExact(final Class<?> messageClass1, final Class<?> messageClass2) {
final ArrayList<Subscription> collection = getExactAsArray(messageClass1, messageClass2); final ArrayList<Subscription> collection = getExactAsArray(messageClass1, messageClass2);
if (collection != null) { if (collection != null) {
@ -233,7 +245,8 @@ public class MultiArgSubscriber implements Subscriber {
// can return null // can return null
@Override @Override
public Subscription[] getExact(final Class<?> messageClass1, final Class<?> messageClass2, final Class<?> messageClass3) { public
Subscription[] getExact(final Class<?> messageClass1, final Class<?> messageClass2, final Class<?> messageClass3) {
final ArrayList<Subscription> collection = getExactAsArray(messageClass1, messageClass2, messageClass3); final ArrayList<Subscription> collection = getExactAsArray(messageClass1, messageClass2, messageClass3);
@ -251,7 +264,8 @@ public class MultiArgSubscriber implements Subscriber {
// can return null // can return null
@Override @Override
public Subscription[] getExactAndSuper(final Class<?> messageClass1, final Class<?> messageClass2) { public
Subscription[] getExactAndSuper(final Class<?> messageClass1, final Class<?> messageClass2) {
ArrayList<Subscription> collection = getExactAsArray(messageClass1, messageClass2); // can return null ArrayList<Subscription> collection = getExactAsArray(messageClass1, messageClass2); // can return null
// now publish superClasses // now publish superClasses
@ -281,7 +295,8 @@ public class MultiArgSubscriber implements Subscriber {
// can return null // can return null
@Override @Override
public Subscription[] getExactAndSuper(final Class<?> messageClass1, final Class<?> messageClass2, final Class<?> messageClass3) { public
Subscription[] getExactAndSuper(final Class<?> messageClass1, final Class<?> messageClass2, final Class<?> messageClass3) {
ArrayList<Subscription> collection = getExactAsArray(messageClass1, messageClass2, messageClass3); // can return null ArrayList<Subscription> collection = getExactAsArray(messageClass1, messageClass2, messageClass3); // can return null

View File

@ -5,7 +5,8 @@ import dorkbox.util.messagebus.utils.VarArgUtils;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicBoolean;
public interface Subscriber { public
interface Subscriber {
float LOAD_FACTOR = 0.8F; float LOAD_FACTOR = 0.8F;
AtomicBoolean getVarArgPossibility(); AtomicBoolean getVarArgPossibility();

View File

@ -15,10 +15,10 @@ import java.util.concurrent.atomic.AtomicInteger;
* A subscription is a thread-safe container that manages exactly one message handler of all registered * A subscription is a thread-safe container that manages exactly one message handler of all registered
* message listeners of the same class, i.e. all subscribed instances (excluding subclasses) of a SingleMessageHandler.class * message listeners of the same class, i.e. all subscribed instances (excluding subclasses) of a SingleMessageHandler.class
* will be referenced in the subscription created for SingleMessageHandler.class. * will be referenced in the subscription created for SingleMessageHandler.class.
* <p> * <p/>
* There will be as many unique subscription objects per message listener class as there are message handlers * There will be as many unique subscription objects per message listener class as there are message handlers
* defined in the message listeners class hierarchy. * defined in the message listeners class hierarchy.
* <p> * <p/>
* The subscription provides functionality for message publication by means of delegation to the respective * The subscription provides functionality for message publication by means of delegation to the respective
* message dispatcher. * message dispatcher.
* *
@ -26,7 +26,8 @@ import java.util.concurrent.atomic.AtomicInteger;
* @author dorkbox, llc * @author dorkbox, llc
* Date: 2/2/15 * Date: 2/2/15
*/ */
public final class Subscription { public final
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(); public final int ID = ID_COUNTER.getAndIncrement();
@ -37,7 +38,8 @@ public final class Subscription {
private final IHandlerInvocation invocation; private final IHandlerInvocation invocation;
private final Collection<Object> listeners; private final Collection<Object> listeners;
public Subscription(final MessageHandler handler, final float loadFactor, final int stripeSize) { public
Subscription(final MessageHandler handler, final float loadFactor, final int stripeSize) {
this.handlerMetadata = handler; this.handlerMetadata = handler;
this.listeners = new StrongConcurrentSetV8<Object>(16, loadFactor, stripeSize); this.listeners = new StrongConcurrentSetV8<Object>(16, loadFactor, stripeSize);
// this.listeners = new StrongConcurrentSet<Object>(16, 0.85F); // this.listeners = new StrongConcurrentSet<Object>(16, 0.85F);
@ -52,31 +54,37 @@ public final class Subscription {
this.invocation = invocation; this.invocation = invocation;
} }
public MessageHandler getHandler() { public
MessageHandler getHandler() {
return handlerMetadata; return handlerMetadata;
} }
public boolean isEmpty() { public
boolean isEmpty() {
return this.listeners.isEmpty(); return this.listeners.isEmpty();
} }
public void subscribe(Object listener) { public
void subscribe(Object listener) {
this.listeners.add(listener); this.listeners.add(listener);
} }
/** /**
* @return TRUE if the element was removed * @return TRUE if the element was removed
*/ */
public boolean unsubscribe(Object existingListener) { public
boolean unsubscribe(Object existingListener) {
return this.listeners.remove(existingListener); return this.listeners.remove(existingListener);
} }
// only used in unit-test // only used in unit-test
public int size() { public
int size() {
return this.listeners.size(); return this.listeners.size();
} }
public void publish(final Object message) throws Throwable { public
void publish(final Object message) throws Throwable {
final MethodAccess handler = this.handlerMetadata.getHandler(); final MethodAccess handler = this.handlerMetadata.getHandler();
final int handleIndex = this.handlerMetadata.getMethodIndex(); final int handleIndex = this.handlerMetadata.getMethodIndex();
final IHandlerInvocation invocation = this.invocation; final IHandlerInvocation invocation = this.invocation;
@ -91,7 +99,8 @@ public final class Subscription {
} }
} }
public void publish(final Object message1, final Object message2) throws Throwable { public
void publish(final Object message1, final Object message2) throws Throwable {
final MethodAccess handler = this.handlerMetadata.getHandler(); final MethodAccess handler = this.handlerMetadata.getHandler();
final int handleIndex = this.handlerMetadata.getMethodIndex(); final int handleIndex = this.handlerMetadata.getMethodIndex();
final IHandlerInvocation invocation = this.invocation; final IHandlerInvocation invocation = this.invocation;
@ -106,7 +115,8 @@ public final class Subscription {
} }
} }
public void publish(final Object message1, final Object message2, final Object message3) throws Throwable { public
void publish(final Object message1, final Object message2, final Object message3) throws Throwable {
final MethodAccess handler = this.handlerMetadata.getHandler(); final MethodAccess handler = this.handlerMetadata.getHandler();
final int handleIndex = this.handlerMetadata.getMethodIndex(); final int handleIndex = this.handlerMetadata.getMethodIndex();
final IHandlerInvocation invocation = this.invocation; final IHandlerInvocation invocation = this.invocation;
@ -121,7 +131,8 @@ public final class Subscription {
} }
} }
public void publishToSubscription(final Object... messages) throws Throwable { public
void publishToSubscription(final Object... messages) throws Throwable {
final MethodAccess handler = this.handlerMetadata.getHandler(); final MethodAccess handler = this.handlerMetadata.getHandler();
final int handleIndex = this.handlerMetadata.getMethodIndex(); final int handleIndex = this.handlerMetadata.getMethodIndex();
final IHandlerInvocation invocation = this.invocation; final IHandlerInvocation invocation = this.invocation;
@ -138,12 +149,14 @@ public final class Subscription {
@Override @Override
public int hashCode() { public
int hashCode() {
return this.ID; return this.ID;
} }
@Override @Override
public boolean equals(Object obj) { public
boolean equals(Object obj) {
if (this == obj) { if (this == obj) {
return true; return true;
} }

View File

@ -15,7 +15,8 @@ import java.util.Map;
* @author dorkbox, llc * @author dorkbox, llc
* Date: 2/2/15 * Date: 2/2/15
*/ */
public final class SubscriptionManager { public final
class SubscriptionManager {
// remember already processed classes that do not contain any message handlers // remember already processed classes that do not contain any message handlers
private final Map<Class<?>, Boolean> nonListeners; private final Map<Class<?>, Boolean> nonListeners;
@ -31,27 +32,30 @@ public final class SubscriptionManager {
private final Subscriber subscriber; private final Subscriber subscriber;
public SubscriptionManager(final int numberOfThreads, final Subscriber subscriber, final StampedLock lock) { public
SubscriptionManager(final int numberOfThreads, final Subscriber subscriber, final StampedLock lock) {
this.numberOfThreads = numberOfThreads; this.numberOfThreads = numberOfThreads;
this.subscriber = subscriber; this.subscriber = subscriber;
this.lock = lock; this.lock = lock;
// modified ONLY during SUB/UNSUB // modified ONLY during SUB/UNSUB
this.nonListeners = JavaVersionAdapter.get.concurrentMap(4, Subscriber.LOAD_FACTOR, numberOfThreads); this.nonListeners = JavaVersionAdapter.concurrentMap(4, Subscriber.LOAD_FACTOR, numberOfThreads);
// only used during SUB/UNSUB, in a rw lock // only used during SUB/UNSUB, in a rw lock
this.subscriptionsPerListener = JavaVersionAdapter.get.concurrentMap(32, Subscriber.LOAD_FACTOR, 1); this.subscriptionsPerListener = JavaVersionAdapter.concurrentMap(32, Subscriber.LOAD_FACTOR, 1);
} }
public void shutdown() { public
void shutdown() {
this.nonListeners.clear(); this.nonListeners.clear();
subscriber.shutdown(); subscriber.shutdown();
this.subscriptionsPerListener.clear(); this.subscriptionsPerListener.clear();
} }
public void subscribe(final Object listener) { public
void subscribe(final Object listener) {
if (listener == null) { if (listener == null) {
return; return;
} }
@ -133,7 +137,8 @@ public final class SubscriptionManager {
} }
} }
public void unsubscribe(final Object listener) { public
void unsubscribe(final Object listener) {
if (listener == null) { if (listener == null) {
return; return;
} }
@ -158,7 +163,8 @@ public final class SubscriptionManager {
} }
} }
private Subscription[] getListenerSubs(final Class<?> listenerClass) { private
Subscription[] getListenerSubs(final Class<?> listenerClass) {
final StampedLock lock = this.lock; final StampedLock lock = this.lock;
final long stamp = lock.readLock(); final long stamp = lock.readLock();

View File

@ -7,25 +7,28 @@ import java.util.ArrayList;
import java.util.HashSet; import java.util.HashSet;
import java.util.Map; import java.util.Map;
public final class ClassUtils { public final
class ClassUtils {
private final Map<Class<?>, Class<?>> arrayCache; private final Map<Class<?>, Class<?>> arrayCache;
private final Map<Class<?>, Class<?>[]> superClassesCache; private final Map<Class<?>, Class<?>[]> superClassesCache;
public ClassUtils(final float loadFactor) { public
this.arrayCache = JavaVersionAdapter.get.concurrentMap(32, loadFactor, 1); ClassUtils(final float loadFactor) {
this.superClassesCache = JavaVersionAdapter.get.concurrentMap(32, loadFactor, 1); this.arrayCache = JavaVersionAdapter.concurrentMap(32, loadFactor, 1);
this.superClassesCache = JavaVersionAdapter.concurrentMap(32, loadFactor, 1);
} }
/** /**
* never returns null * never returns null
* never reset, since it never needs to be reset (as the class hierarchy doesn't change at runtime) * never reset, since it never needs to be reset (as the class hierarchy doesn't change at runtime)
* <p> * <p/>
* if parameter clazz is of type array, then the super classes are of array type as well * if parameter clazz is of type array, then the super classes are of array type as well
* <p> * <p/>
* protected by read lock by caller. The cache version is called first, by write lock * protected by read lock by caller. The cache version is called first, by write lock
*/ */
public Class<?>[] getSuperClasses(final Class<?> clazz) { public
Class<?>[] getSuperClasses(final Class<?> clazz) {
// this is never reset, since it never needs to be. // this is never reset, since it never needs to be.
final Map<Class<?>, Class<?>[]> local = this.superClassesCache; final Map<Class<?>, Class<?>[]> local = this.superClassesCache;
@ -75,7 +78,8 @@ public final class ClassUtils {
* never returns null * never returns null
* never reset * never reset
*/ */
public Class<?> getArrayClass(final Class<?> c) { public
Class<?> getArrayClass(final Class<?> c) {
final Map<Class<?>, Class<?>> arrayCache = this.arrayCache; final Map<Class<?>, Class<?>> arrayCache = this.arrayCache;
Class<?> clazz = arrayCache.get(c); Class<?> clazz = arrayCache.get(c);
@ -93,12 +97,14 @@ public final class ClassUtils {
/** /**
* Clears the caches * Clears the caches
*/ */
public void clear() { public
void clear() {
this.arrayCache.clear(); this.arrayCache.clear();
this.superClassesCache.clear(); this.superClassesCache.clear();
} }
public static <T> ArrayList<T> findCommon(final T[] arrayOne, final T[] arrayTwo) { public static
<T> ArrayList<T> findCommon(final T[] arrayOne, final T[] arrayTwo) {
T[] arrayToHash; T[] arrayToHash;
T[] arrayToSearch; T[] arrayToSearch;
@ -141,7 +147,8 @@ public final class ClassUtils {
return intersection; return intersection;
} }
public static <T> ArrayList<T> findCommon(final ArrayList<T> arrayOne, final ArrayList<T> arrayTwo) { public static
<T> ArrayList<T> findCommon(final ArrayList<T> arrayOne, final ArrayList<T> arrayTwo) {
ArrayList<T> arrayToHash; ArrayList<T> arrayToHash;
ArrayList<T> arrayToSearch; ArrayList<T> arrayToSearch;

View File

@ -16,12 +16,15 @@ import java.util.HashSet;
* @author dorkbox * @author dorkbox
* Date: 2/2/15 * Date: 2/2/15
*/ */
public final class ReflectionUtils { public final
class ReflectionUtils {
private ReflectionUtils() { private
ReflectionUtils() {
} }
public static Method[] getMethods(Class<?> target) { public static
Method[] getMethods(Class<?> target) {
ArrayList<Method> methods = new ArrayList<Method>(); ArrayList<Method> methods = new ArrayList<Method>();
getMethods(target, methods); getMethods(target, methods);
@ -30,7 +33,8 @@ public final class ReflectionUtils {
return array; return array;
} }
private static void getMethods(Class<?> target, ArrayList<Method> methods) { private static
void getMethods(Class<?> target, ArrayList<Method> methods) {
try { try {
for (Method method : target.getDeclaredMethods()) { for (Method method : target.getDeclaredMethods()) {
if (getAnnotation(method, Handler.class) != null) { if (getAnnotation(method, Handler.class) != null) {
@ -51,7 +55,8 @@ public final class ReflectionUtils {
* for an override of the given methods -> finds the bottom most override of the given * for an override of the given methods -> finds the bottom most override of the given
* method if any exists * method if any exists
*/ */
public static Method getOverridingMethod(final Method overridingMethod, final Class<?> subclass) { public static
Method getOverridingMethod(final Method overridingMethod, final Class<?> subclass) {
Class<?> current = subclass; Class<?> current = subclass;
while (!current.equals(overridingMethod.getDeclaringClass())) { while (!current.equals(overridingMethod.getDeclaringClass())) {
try { try {
@ -70,7 +75,8 @@ public final class ReflectionUtils {
* @param from The root class to start with * @param from The root class to start with
* @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 Class<?>[] getSuperTypes(Class<?> from) { public static
Class<?>[] getSuperTypes(Class<?> from) {
ArrayList<Class<?>> superclasses = new ArrayList<Class<?>>(); ArrayList<Class<?>> superclasses = new ArrayList<Class<?>>();
collectInterfaces(from, superclasses); collectInterfaces(from, superclasses);
@ -86,14 +92,16 @@ public final class ReflectionUtils {
return classes; return classes;
} }
public static void collectInterfaces(Class<?> from, Collection<Class<?>> accumulator) { public static
void collectInterfaces(Class<?> from, Collection<Class<?>> accumulator) {
for (Class<?> intface : from.getInterfaces()) { for (Class<?> intface : from.getInterfaces()) {
accumulator.add(intface); accumulator.add(intface);
collectInterfaces(intface, accumulator); collectInterfaces(intface, accumulator);
} }
} }
public static boolean containsOverridingMethod(final Method[] allMethods, final Method methodToCheck) { public static
boolean containsOverridingMethod(final Method[] allMethods, final Method methodToCheck) {
final int length = allMethods.length; final int length = allMethods.length;
Method method; Method method;
@ -117,8 +125,8 @@ public final class ReflectionUtils {
* @param <A> Class of annotation type * @param <A> Class of annotation type
* @return Annotation instance or null * @return Annotation instance or null
*/ */
private static <A extends Annotation> A getAnnotation(AnnotatedElement from, Class<A> annotationType, private static
Collection<AnnotatedElement> visited) { <A extends Annotation> A getAnnotation(AnnotatedElement from, Class<A> annotationType, Collection<AnnotatedElement> visited) {
if (visited.contains(from)) { if (visited.contains(from)) {
return null; return null;
} }
@ -136,13 +144,15 @@ public final class ReflectionUtils {
return null; return null;
} }
public static <A extends Annotation> A getAnnotation(AnnotatedElement from, Class<A> annotationType) { public static
<A extends Annotation> A getAnnotation(AnnotatedElement from, Class<A> annotationType) {
A annotation = getAnnotation(from, annotationType, new HashSet<AnnotatedElement>(16)); A annotation = getAnnotation(from, annotationType, new HashSet<AnnotatedElement>(16));
return annotation; return annotation;
} }
// //
private static boolean isOverriddenBy(final Method superclassMethod, final Method subclassMethod) { private static
boolean isOverriddenBy(final Method superclassMethod, final Method subclassMethod) {
// if the declaring classes are the same or the subclass method is not defined in the subclass // if the declaring classes are the same or the subclass method is not defined in the subclass
// hierarchy of the given superclass method or the method names are not the same then // hierarchy of the given superclass method or the method names are not the same then
// subclassMethod does not override superclassMethod // subclassMethod does not override superclassMethod

View File

@ -8,7 +8,8 @@ import dorkbox.util.messagebus.subscription.Subscription;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Map; import java.util.Map;
public final class SubscriptionUtils { public final
class SubscriptionUtils {
private final ClassUtils superClass; private final ClassUtils superClass;
// superClassSubscriptions keeps track of all subscriptions of super classes. SUB/UNSUB dumps it, so it is recreated dynamically. // superClassSubscriptions keeps track of all subscriptions of super classes. SUB/UNSUB dumps it, so it is recreated dynamically.
@ -18,17 +19,19 @@ public final class SubscriptionUtils {
private final HashMapTree<Class<?>, ArrayList<Subscription>> superClassSubscriptionsMulti; private final HashMapTree<Class<?>, ArrayList<Subscription>> superClassSubscriptionsMulti;
public SubscriptionUtils(final ClassUtils superClass, final float loadFactor) { public
SubscriptionUtils(final ClassUtils superClass, final float loadFactor) {
this.superClass = superClass; this.superClass = superClass;
// superClassSubscriptions keeps track of all subscriptions of super classes. SUB/UNSUB dumps it, so it is recreated dynamically. // superClassSubscriptions keeps track of all subscriptions of super classes. SUB/UNSUB dumps it, so it is recreated dynamically.
// it's a hit on SUB/UNSUB, but improves performance of handlers // it's a hit on SUB/UNSUB, but improves performance of handlers
this.superClassSubscriptions = JavaVersionAdapter.get.concurrentMap(8, loadFactor, 1); this.superClassSubscriptions = JavaVersionAdapter.concurrentMap(8, loadFactor, 1);
this.superClassSubscriptionsMulti = new HashMapTree<Class<?>, ArrayList<Subscription>>(4, loadFactor); this.superClassSubscriptionsMulti = new HashMapTree<Class<?>, ArrayList<Subscription>>(4, loadFactor);
} }
public void clear() { public
void clear() {
this.superClassSubscriptions.clear(); this.superClassSubscriptions.clear();
this.superClassSubscriptionsMulti.clear(); this.superClassSubscriptionsMulti.clear();
} }
@ -43,7 +46,8 @@ public final class SubscriptionUtils {
* *
* @return CAN NOT RETURN NULL * @return CAN NOT RETURN NULL
*/ */
public ArrayList<Subscription> getSuperSubscriptions(final Class<?> clazz, final Subscriber subscriber) { public
ArrayList<Subscription> getSuperSubscriptions(final Class<?> clazz, final Subscriber subscriber) {
// whenever our subscriptions change, this map is cleared. // whenever our subscriptions change, this map is cleared.
final Map<Class<?>, ArrayList<Subscription>> local = this.superClassSubscriptions; final Map<Class<?>, ArrayList<Subscription>> local = this.superClassSubscriptions;
@ -95,7 +99,8 @@ public final class SubscriptionUtils {
* *
* @return CAN NOT RETURN NULL * @return CAN NOT RETURN NULL
*/ */
public ArrayList<Subscription> getSuperSubscriptions(final Class<?> clazz1, final Class<?> clazz2, final Subscriber subscriber) { public
ArrayList<Subscription> getSuperSubscriptions(final Class<?> clazz1, final Class<?> clazz2, final Subscriber subscriber) {
// whenever our subscriptions change, this map is cleared. // whenever our subscriptions change, this map is cleared.
final HashMapTree<Class<?>, ArrayList<Subscription>> cached = this.superClassSubscriptionsMulti; final HashMapTree<Class<?>, ArrayList<Subscription>> cached = this.superClassSubscriptionsMulti;
@ -162,8 +167,9 @@ public final class SubscriptionUtils {
* *
* @return CAN NOT RETURN NULL * @return CAN NOT RETURN NULL
*/ */
public ArrayList<Subscription> getSuperSubscriptions(final Class<?> clazz1, final Class<?> clazz2, final Class<?> clazz3, public
final Subscriber subscriber) { ArrayList<Subscription> getSuperSubscriptions(final Class<?> clazz1, final Class<?> clazz2, final Class<?> clazz3,
final Subscriber subscriber) {
// whenever our subscriptions change, this map is cleared. // whenever our subscriptions change, this map is cleared.
final HashMapTree<Class<?>, ArrayList<Subscription>> local = this.superClassSubscriptionsMulti; final HashMapTree<Class<?>, ArrayList<Subscription>> local = this.superClassSubscriptionsMulti;

View File

@ -9,7 +9,8 @@ import dorkbox.util.messagebus.subscription.Subscription;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Map; import java.util.Map;
public final class VarArgUtils { public final
class VarArgUtils {
private final Map<Class<?>, ArrayList<Subscription>> varArgSubscriptionsSingle; private final Map<Class<?>, ArrayList<Subscription>> varArgSubscriptionsSingle;
private final HashMapTree<Class<?>, ArrayList<Subscription>> varArgSubscriptionsMulti; private final HashMapTree<Class<?>, ArrayList<Subscription>> varArgSubscriptionsMulti;
@ -19,19 +20,21 @@ public final class VarArgUtils {
private final ClassUtils superClassUtils; private final ClassUtils superClassUtils;
public VarArgUtils(final ClassUtils superClassUtils, final float loadFactor) { public
VarArgUtils(final ClassUtils superClassUtils, final float loadFactor) {
this.superClassUtils = superClassUtils; this.superClassUtils = superClassUtils;
this.varArgSubscriptionsSingle = JavaVersionAdapter.get.concurrentMap(16, loadFactor, 1); this.varArgSubscriptionsSingle = JavaVersionAdapter.concurrentMap(16, loadFactor, 1);
this.varArgSubscriptionsMulti = new HashMapTree<Class<?>, ArrayList<Subscription>>(4, loadFactor); this.varArgSubscriptionsMulti = new HashMapTree<Class<?>, ArrayList<Subscription>>(4, loadFactor);
this.varArgSuperSubscriptionsSingle = JavaVersionAdapter.get.concurrentMap(16, loadFactor, 1); this.varArgSuperSubscriptionsSingle = JavaVersionAdapter.concurrentMap(16, loadFactor, 1);
this.varArgSuperSubscriptionsMulti = new HashMapTree<Class<?>, ArrayList<Subscription>>(4, loadFactor); this.varArgSuperSubscriptionsMulti = new HashMapTree<Class<?>, ArrayList<Subscription>>(4, loadFactor);
} }
public void clear() { public
void clear() {
this.varArgSubscriptionsSingle.clear(); this.varArgSubscriptionsSingle.clear();
this.varArgSubscriptionsMulti.clear(); this.varArgSubscriptionsMulti.clear();
@ -43,7 +46,8 @@ public final class VarArgUtils {
// CAN NOT RETURN NULL // CAN NOT RETURN NULL
// check to see if the messageType can convert/publish to the "array" version, without the hit to JNI // check to see if the messageType can convert/publish to the "array" version, without the hit to JNI
// and then, returns the array'd version subscriptions // and then, returns the array'd version subscriptions
public Subscription[] getVarArgSubscriptions(final Class<?> messageClass, final Subscriber subscriber) { public
Subscription[] getVarArgSubscriptions(final Class<?> messageClass, final Subscriber subscriber) {
// whenever our subscriptions change, this map is cleared. // whenever our subscriptions change, this map is cleared.
final Map<Class<?>, ArrayList<Subscription>> local = this.varArgSubscriptionsSingle; final Map<Class<?>, ArrayList<Subscription>> local = this.varArgSubscriptionsSingle;
@ -84,7 +88,8 @@ public final class VarArgUtils {
// CAN NOT RETURN NULL // CAN NOT RETURN NULL
// check to see if the messageType can convert/publish to the "array" superclass version, without the hit to JNI // check to see if the messageType can convert/publish to the "array" superclass version, without the hit to JNI
// and then, returns the array'd version superclass subscriptions // and then, returns the array'd version superclass subscriptions
public Subscription[] getVarArgSuperSubscriptions(final Class<?> messageClass, final Subscriber subscriber) { public
Subscription[] getVarArgSuperSubscriptions(final Class<?> messageClass, final Subscriber subscriber) {
final ArrayList<Subscription> subs = getVarArgSuperSubscriptions_List(messageClass, subscriber); final ArrayList<Subscription> subs = getVarArgSuperSubscriptions_List(messageClass, subscriber);
final Subscription[] returnedSubscriptions = new Subscription[subs.size()]; final Subscription[] returnedSubscriptions = new Subscription[subs.size()];
@ -93,7 +98,8 @@ public final class VarArgUtils {
} }
// CAN NOT RETURN NULL // CAN NOT RETURN NULL
private ArrayList<Subscription> getVarArgSuperSubscriptions_List(final Class<?> messageClass, final Subscriber subscriber) { private
ArrayList<Subscription> getVarArgSuperSubscriptions_List(final Class<?> messageClass, final Subscriber subscriber) {
// whenever our subscriptions change, this map is cleared. // whenever our subscriptions change, this map is cleared.
final Map<Class<?>, ArrayList<Subscription>> local = this.varArgSuperSubscriptionsSingle; final Map<Class<?>, ArrayList<Subscription>> local = this.varArgSuperSubscriptionsSingle;
@ -151,7 +157,8 @@ public final class VarArgUtils {
// CAN NOT RETURN NULL // CAN NOT RETURN NULL
// check to see if the messageType can convert/publish to the "array" superclass version, without the hit to JNI // check to see if the messageType can convert/publish to the "array" superclass version, without the hit to JNI
// and then, returns the array'd version superclass subscriptions // and then, returns the array'd version superclass subscriptions
public Subscription[] getVarArgSuperSubscriptions(final Class<?> messageClass1, final Class<?> messageClass2, final Subscriber subscriber) { public
Subscription[] getVarArgSuperSubscriptions(final Class<?> messageClass1, final Class<?> messageClass2, final Subscriber subscriber) {
// whenever our subscriptions change, this map is cleared. // whenever our subscriptions change, this map is cleared.
final HashMapTree<Class<?>, ArrayList<Subscription>> local = this.varArgSuperSubscriptionsMulti; final HashMapTree<Class<?>, ArrayList<Subscription>> local = this.varArgSuperSubscriptionsMulti;
@ -178,8 +185,9 @@ public final class VarArgUtils {
// CAN NOT RETURN NULL // CAN NOT RETURN NULL
// check to see if the messageType can convert/publish to the "array" superclass version, without the hit to JNI // check to see if the messageType can convert/publish to the "array" superclass version, without the hit to JNI
// and then, returns the array'd version superclass subscriptions // and then, returns the array'd version superclass subscriptions
public Subscription[] getVarArgSuperSubscriptions(final Class<?> messageClass1, final Class<?> messageClass2, public
final Class<?> messageClass3, final Subscriber subscriber) { Subscription[] getVarArgSuperSubscriptions(final Class<?> messageClass1, final Class<?> messageClass2, final Class<?> messageClass3,
final Subscriber subscriber) {
// whenever our subscriptions change, this map is cleared. // whenever our subscriptions change, this map is cleared.
final HashMapTree<Class<?>, ArrayList<Subscription>> local = this.varArgSuperSubscriptionsMulti; final HashMapTree<Class<?>, ArrayList<Subscription>> local = this.varArgSuperSubscriptionsMulti;

View File

@ -15,7 +15,8 @@ import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.LinkedTransferQueue; import java.util.concurrent.LinkedTransferQueue;
public class PerfTest_Collections { public
class PerfTest_Collections {
public static final int REPETITIONS = 10 * 1000 * 100; public static final int REPETITIONS = 10 * 1000 * 100;
public static final Integer TEST_VALUE = Integer.valueOf(777); public static final Integer TEST_VALUE = Integer.valueOf(777);
@ -24,7 +25,8 @@ public class PerfTest_Collections {
private static final MessageHandler[] allHandlers = MessageHandler.get(Listener.class); private static final MessageHandler[] allHandlers = MessageHandler.get(Listener.class);
public static void main(final String[] args) throws Exception { public static
void main(final String[] args) throws Exception {
final int size = 16; final int size = 16;
@ -33,52 +35,56 @@ public class PerfTest_Collections {
// have to warm-up the JVM. // have to warm-up the JVM.
System.err.print("\nWarming up JVM."); System.err.print("\nWarming up JVM.");
// for (int i=0;i<2;i++) { // for (int i=0;i<2;i++) {
bench(size, new ConcurrentLinkedQueue<Subscription>(), false); bench(size, new ConcurrentLinkedQueue<Subscription>(), false);
System.err.print("."); System.err.print(".");
bench(size, new ArrayList<Subscription>(size*2), false); bench(size, new ArrayList<Subscription>(size * 2), false);
System.err.print("."); System.err.print(".");
bench(size, new ArrayDeque<Subscription>(size*2), false); bench(size, new ArrayDeque<Subscription>(size * 2), false);
System.err.print("."); System.err.print(".");
bench(size, new ConcurrentLinkedQueue<Subscription>(), false); bench(size, new ConcurrentLinkedQueue<Subscription>(), false);
System.err.print("."); System.err.print(".");
bench(size, new LinkedList<Subscription>(), false); bench(size, new LinkedList<Subscription>(), false);
System.err.print("."); System.err.print(".");
// } // }
System.err.println("Done"); System.err.println("Done");
bench(size, new ArrayList<Subscription>(size*2)); bench(size, new ArrayList<Subscription>(size * 2));
bench(size, new ConcurrentSet<Subscription>(size*2, LOAD_FACTOR, 5)); bench(size, new ConcurrentSet<Subscription>(size * 2, LOAD_FACTOR, 5));
bench(size, new ConcurrentLinkedQueue2<Subscription>()); bench(size, new ConcurrentLinkedQueue2<Subscription>());
bench(size, new ConcurrentLinkedQueue<Subscription>()); bench(size, new ConcurrentLinkedQueue<Subscription>());
bench(size, new LinkedTransferQueue<Subscription>()); bench(size, new LinkedTransferQueue<Subscription>());
bench(size, new ArrayDeque<Subscription>(size*2)); bench(size, new ArrayDeque<Subscription>(size * 2));
bench(size, new LinkedList<Subscription>()); bench(size, new LinkedList<Subscription>());
bench(size, new StrongConcurrentSetV8<Subscription>(size*2, LOAD_FACTOR)); bench(size, new StrongConcurrentSetV8<Subscription>(size * 2, LOAD_FACTOR));
bench(size, new StrongConcurrentSet<Subscription>(size*2, LOAD_FACTOR)); bench(size, new StrongConcurrentSet<Subscription>(size * 2, LOAD_FACTOR));
bench(size, Collections.newSetFromMap(new ConcurrentHashMap<Subscription, Boolean>(size*2, LOAD_FACTOR, 1))); bench(size, Collections.newSetFromMap(new ConcurrentHashMap<Subscription, Boolean>(size * 2, LOAD_FACTOR, 1)));
bench(size, new HashSet<Subscription>()); bench(size, new HashSet<Subscription>());
// bench(size, new ConcurrentSkipListSet<Subscription>()); // needs comparable // bench(size, new ConcurrentSkipListSet<Subscription>()); // needs comparable
} }
public static void bench(final int size, Collection<Subscription> set) throws Exception { public static
void bench(final int size, Collection<Subscription> set) throws Exception {
bench(size, set, true); bench(size, set, true);
} }
public static void bench(final int size, Collection<Subscription> set, boolean showOutput) throws Exception {
public static
void bench(final int size, Collection<Subscription> set, boolean showOutput) throws Exception {
final int warmupRuns = 2; final int warmupRuns = 2;
final int runs = 3; final int runs = 3;
for (int i=0;i<size;i++) { for (int i = 0; i < size; i++) {
for (MessageHandler x : allHandlers) { for (MessageHandler x : allHandlers) {
set.add(new Subscription(x, .85F, 1)); set.add(new Subscription(x, .85F, 1));
} }
} }
if (!showOutput) { if (!showOutput) {
for (int i=2;i<6;i++) { for (int i = 2; i < 6; i++) {
averageRun(warmupRuns, runs, set, false, i, REPETITIONS); averageRun(warmupRuns, runs, set, false, i, REPETITIONS);
} }
} else { }
for (int i=1;i<10;i++) { else {
for (int i = 1; i < 10; i++) {
long average = averageRun(warmupRuns, runs, set, false, i, REPETITIONS); long average = averageRun(warmupRuns, runs, set, false, i, REPETITIONS);
System.out.format("summary,IteratorPerfTest,%s - %,d (%d)\n", set.getClass().getSimpleName(), average, i); System.out.format("summary,IteratorPerfTest,%s - %,d (%d)\n", set.getClass().getSimpleName(), average, i);
} }
@ -87,11 +93,13 @@ public class PerfTest_Collections {
set.clear(); set.clear();
} }
public static long averageRun(int warmUpRuns, int sumCount, Collection<Subscription> set, boolean showStats, int concurrency, int repetitions) throws Exception { public static
long averageRun(int warmUpRuns, int sumCount, Collection<Subscription> set, boolean showStats, int concurrency, int repetitions)
throws Exception {
int runs = warmUpRuns + sumCount; int runs = warmUpRuns + sumCount;
final long[] results = new long[runs]; final long[] results = new long[runs];
for (int i = 0; i < runs; i++) { for (int i = 0; i < runs; i++) {
WeakReference<Object> weakReference = new WeakReference<>(new Object()); WeakReference<Object> weakReference = new WeakReference<Object>(new Object());
while (weakReference.get() != null) { while (weakReference.get() != null) {
System.gc(); System.gc();
Thread.sleep(100L); Thread.sleep(100L);
@ -104,24 +112,25 @@ public class PerfTest_Collections {
sum += results[i]; sum += results[i];
} }
return sum/sumCount; return sum / sumCount;
} }
private static long performanceRun(int runNumber, Collection<Subscription> set, boolean showStats, int concurrency, int repetitions) throws Exception { private static
long performanceRun(int runNumber, Collection<Subscription> set, boolean showStats, int concurrency, int repetitions) throws Exception {
Producer[] producers = new Producer[concurrency]; Producer[] producers = new Producer[concurrency];
Thread[] threads = new Thread[concurrency*2]; Thread[] threads = new Thread[concurrency * 2];
for (int i=0;i<concurrency;i++) { for (int i = 0; i < concurrency; i++) {
producers[i] = new Producer(set, repetitions); producers[i] = new Producer(set, repetitions);
threads[i] = new Thread(producers[i], "Producer " + i); threads[i] = new Thread(producers[i], "Producer " + i);
} }
for (int i=0;i<concurrency;i++) { for (int i = 0; i < concurrency; i++) {
threads[i].start(); threads[i].start();
} }
for (int i=0;i<concurrency;i++) { for (int i = 0; i < concurrency; i++) {
threads[i].join(); threads[i].join();
} }
@ -129,7 +138,7 @@ public class PerfTest_Collections {
long end = -1; long end = -1;
long count = 0; long count = 0;
for (int i=0;i<concurrency;i++) { for (int i = 0; i < concurrency; i++) {
if (producers[i].start < start) { if (producers[i].start < start) {
start = producers[i].start; start = producers[i].start;
} }
@ -143,7 +152,7 @@ public class PerfTest_Collections {
long duration = end - start; long duration = end - start;
long ops = repetitions * 1_000_000_000L / duration; long ops = repetitions * 1000000000L / duration;
if (showStats) { if (showStats) {
System.out.format("%d (%d) - ops/sec=%,d\n", runNumber, count, ops); System.out.format("%d (%d) - ops/sec=%,d\n", runNumber, count, ops);
@ -151,21 +160,24 @@ public class PerfTest_Collections {
return ops; return ops;
} }
public static class Producer implements Runnable { public static
class Producer implements Runnable {
private final Collection<Subscription> set; private final Collection<Subscription> set;
volatile long start; volatile long start;
volatile long end; volatile long end;
private int repetitions; private int repetitions;
volatile int count; volatile int count;
public Producer(Collection<Subscription> set, int repetitions) { public
Producer(Collection<Subscription> set, int repetitions) {
this.set = set; this.set = set;
this.repetitions = repetitions; this.repetitions = repetitions;
} }
@SuppressWarnings("unused") @SuppressWarnings("unused")
@Override @Override
public void run() { public
void run() {
Collection<Subscription> set = this.set; Collection<Subscription> set = this.set;
int i = this.repetitions; int i = this.repetitions;
this.start = System.nanoTime(); this.start = System.nanoTime();
@ -178,7 +190,7 @@ public class PerfTest_Collections {
int count = 0; int count = 0;
do { do {
for (iterator = set.iterator(); iterator.hasNext();) { for (iterator = set.iterator(); iterator.hasNext(); ) {
sub = iterator.next(); sub = iterator.next();
// if (sub.acceptsSubtypes()) { // if (sub.acceptsSubtypes()) {
// count--; // count--;
@ -201,14 +213,18 @@ public class PerfTest_Collections {
} }
} }
@SuppressWarnings("unused") @SuppressWarnings("unused")
public static class Listener { public static
class Listener {
@Handler @Handler
public void handleSync(Integer o1) { public
void handleSync(Integer o1) {
} }
@Handler(acceptVarargs=true) @Handler(acceptVarargs = true)
public void handleSync(Object... o) { public
void handleSync(Object... o) {
} }
} }
} }

View File

@ -3,13 +3,15 @@ package dorkbox.util.messagebus;
import dorkbox.util.messagebus.annotations.Handler; import dorkbox.util.messagebus.annotations.Handler;
public class PerfTest_MBassador { public
class PerfTest_MBassador {
public static final int REPETITIONS = 50 * 1000 * 100; public static final int REPETITIONS = 50 * 1000 * 100;
public static final Integer TEST_VALUE = Integer.valueOf(777); public static final Integer TEST_VALUE = Integer.valueOf(777);
private static final int concurrency = 1; private static final int concurrency = 1;
public static void main(final String[] args) throws Exception { public static
void main(final String[] args) throws Exception {
System.out.println("reps:" + REPETITIONS + " Concurrency " + concurrency); System.out.println("reps:" + REPETITIONS + " Concurrency " + concurrency);
final int warmupRuns = 4; final int warmupRuns = 4;
@ -24,8 +26,8 @@ public class PerfTest_MBassador {
System.out.format("summary,PublishPerfTest, %,d\n", average); System.out.format("summary,PublishPerfTest, %,d\n", average);
} }
public static long averageRun(int warmUpRuns, int sumCount, MessageBus bus, boolean showStats, int concurrency, int repetitions) public static
throws Exception { long averageRun(int warmUpRuns, int sumCount, MessageBus bus, boolean showStats, int concurrency, int repetitions) throws Exception {
int runs = warmUpRuns + sumCount; int runs = warmUpRuns + sumCount;
final long[] results = new long[runs]; final long[] results = new long[runs];
for (int i = 0; i < runs; i++) { for (int i = 0; i < runs; i++) {
@ -38,32 +40,32 @@ public class PerfTest_MBassador {
sum += results[i]; sum += results[i];
} }
return sum/sumCount; return sum / sumCount;
} }
private static long performanceRun(int runNumber, MessageBus bus, boolean showStats, int concurrency, int repetitions) private static
throws Exception { long performanceRun(int runNumber, MessageBus bus, boolean showStats, int concurrency, int repetitions) throws Exception {
Producer[] producers = new Producer[concurrency]; Producer[] producers = new Producer[concurrency];
Thread[] threads = new Thread[concurrency*2]; Thread[] threads = new Thread[concurrency * 2];
for (int i=0;i<concurrency;i++) { for (int i = 0; i < concurrency; i++) {
producers[i] = new Producer(bus, repetitions); producers[i] = new Producer(bus, repetitions);
threads[i] = new Thread(producers[i], "Producer " + i); threads[i] = new Thread(producers[i], "Producer " + i);
} }
for (int i=0;i<concurrency;i++) { for (int i = 0; i < concurrency; i++) {
threads[i].start(); threads[i].start();
} }
for (int i=0;i<concurrency;i++) { for (int i = 0; i < concurrency; i++) {
threads[i].join(); threads[i].join();
} }
long start = Long.MAX_VALUE; long start = Long.MAX_VALUE;
long end = -1; long end = -1;
for (int i=0;i<concurrency;i++) { for (int i = 0; i < concurrency; i++) {
if (producers[i].start < start) { if (producers[i].start < start) {
start = producers[i].start; start = producers[i].start;
} }
@ -75,7 +77,7 @@ public class PerfTest_MBassador {
long duration = end - start; long duration = end - start;
long ops = repetitions * 1_000_000_000L / duration; long ops = repetitions * 1000000000L / duration;
if (showStats) { if (showStats) {
System.out.format("%d - ops/sec=%,d\n", runNumber, ops); System.out.format("%d - ops/sec=%,d\n", runNumber, ops);
@ -83,19 +85,22 @@ public class PerfTest_MBassador {
return ops; return ops;
} }
public static class Producer implements Runnable { public static
class Producer implements Runnable {
private final MessageBus bus; private final MessageBus bus;
volatile long start; volatile long start;
volatile long end; volatile long end;
private int repetitions; private int repetitions;
public Producer(MessageBus bus, int repetitions) { public
Producer(MessageBus bus, int repetitions) {
this.bus = bus; this.bus = bus;
this.repetitions = repetitions; this.repetitions = repetitions;
} }
@Override @Override
public void run() { public
void run() {
MessageBus bus = this.bus; MessageBus bus = this.bus;
int i = this.repetitions; int i = this.repetitions;
this.start = System.nanoTime(); this.start = System.nanoTime();
@ -108,14 +113,18 @@ public class PerfTest_MBassador {
} }
} }
@SuppressWarnings("unused") @SuppressWarnings("unused")
public static class Listener { public static
class Listener {
@Handler @Handler
public void handleSync(Integer o1) { public
void handleSync(Integer o1) {
} }
@Handler(acceptVarargs=true) @Handler(acceptVarargs = true)
public void handleSync(Object... o) { public
void handleSync(Object... o) {
} }
} }
} }