Added intellij support. Compiled as java6, supports java8 ConcurrentHashMap
parent
894da4c980
commit
8f312a8012
|
@ -3,7 +3,7 @@ package dorkbox.util.messagebus;
|
|||
import org.jctools.queues.MpmcArrayQueue;
|
||||
import org.jctools.util.UnsafeAccess;
|
||||
|
||||
import java.util.concurrent.ThreadLocalRandom;
|
||||
import java.util.Random;
|
||||
|
||||
|
||||
final
|
||||
|
@ -38,14 +38,6 @@ class MpmcMultiTransferArrayQueue extends MpmcArrayQueue<Object> {
|
|||
*/
|
||||
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>() {
|
||||
@Override
|
||||
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
|
||||
|
@ -714,7 +722,7 @@ class MpmcMultiTransferArrayQueue extends MpmcArrayQueue<Object> {
|
|||
private
|
||||
void park(final Object node, final Thread myThread) throws InterruptedException {
|
||||
int spins = -1; // initialized after first item and cancel checks
|
||||
ThreadLocalRandom randomYields = null; // bound if needed
|
||||
Random randomYields = null; // bound if needed
|
||||
|
||||
for (; ; ) {
|
||||
if (MultiNode.lvThread(node) == null) {
|
||||
|
@ -725,7 +733,7 @@ class MpmcMultiTransferArrayQueue extends MpmcArrayQueue<Object> {
|
|||
}
|
||||
else if (spins < 0) {
|
||||
spins = PARK_UNTIMED_SPINS;
|
||||
randomYields = ThreadLocalRandom.current();
|
||||
randomYields = randomThreadLocal.get();
|
||||
}
|
||||
else if (spins > 0) {
|
||||
if (randomYields.nextInt(1024) == 0) {
|
||||
|
|
|
@ -1,10 +1,6 @@
|
|||
package dorkbox.util.messagebus.annotations;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Inherited;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
import java.lang.annotation.*;
|
||||
|
||||
/**
|
||||
* 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)
|
||||
@Inherited
|
||||
@Target(value = {ElementType.METHOD,ElementType.ANNOTATION_TYPE})
|
||||
public @interface Handler {
|
||||
@Target(value = {ElementType.METHOD, ElementType.ANNOTATION_TYPE})
|
||||
public
|
||||
@interface Handler {
|
||||
|
||||
/**
|
||||
* Define whether or not the handler accepts variable arguments it declares in its signature.
|
||||
|
|
|
@ -1,23 +1,18 @@
|
|||
package dorkbox.util.messagebus.annotations;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Inherited;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
import java.lang.annotation.*;
|
||||
|
||||
/**
|
||||
*
|
||||
* This annotation is meant to carry configuration that is shared among all instances of the annotated
|
||||
* listener. Supported configurations are:
|
||||
*
|
||||
* Reference type: The bus will use either strong or weak references to its registered listeners,
|
||||
* depending on which reference type (@see References) is set
|
||||
* <p/>
|
||||
* Reference type: The bus will use either strong or weak references to its registered listeners,
|
||||
* depending on which reference type (@see References) is set
|
||||
*
|
||||
* @author bennidi
|
||||
*/
|
||||
@Retention(value = RetentionPolicy.RUNTIME)
|
||||
@Target(value = {ElementType.TYPE, ElementType.ANNOTATION_TYPE})
|
||||
@Inherited
|
||||
public @interface Listener {
|
||||
}
|
||||
public
|
||||
@interface Listener {}
|
||||
|
|
|
@ -1,10 +1,6 @@
|
|||
package dorkbox.util.messagebus.annotations;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Inherited;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
import java.lang.annotation.*;
|
||||
|
||||
/**
|
||||
* 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.
|
||||
* This feature will reduce performance of message publication. Try to avoid shared mutable state whenever possible
|
||||
* and use immutable data instead.
|
||||
*
|
||||
* <p/>
|
||||
* Note: Unsynchronized handlers may still be invoked concurrently with synchronized ones
|
||||
*
|
||||
*
|
||||
*
|
||||
* @author bennidi
|
||||
* Date: 3/31/13
|
||||
*/
|
||||
@Retention(value = RetentionPolicy.RUNTIME)
|
||||
@Inherited
|
||||
@Target(value = {ElementType.METHOD, ElementType.ANNOTATION_TYPE})
|
||||
public @interface Synchronized {
|
||||
}
|
||||
public
|
||||
@interface Synchronized {}
|
||||
|
|
|
@ -16,7 +16,8 @@ import java.util.concurrent.atomic.AtomicLong;
|
|||
* @author bennidi
|
||||
* 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 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;
|
||||
|
||||
|
||||
protected AbstractConcurrentSet(Map<T, ISetEntry<T>> entries) {
|
||||
protected
|
||||
AbstractConcurrentSet(Map<T, ISetEntry<T>> 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
|
||||
public boolean add(T element) {
|
||||
public
|
||||
boolean add(T element) {
|
||||
if (element == null) {
|
||||
return false;
|
||||
}
|
||||
|
@ -62,7 +66,8 @@ public abstract class AbstractConcurrentSet<T> implements Set<T> {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean contains(Object element) {
|
||||
public
|
||||
boolean contains(Object element) {
|
||||
final StampedLock lock = this.lock;
|
||||
long stamp = lock.readLock();
|
||||
|
||||
|
@ -73,7 +78,8 @@ public abstract class AbstractConcurrentSet<T> implements Set<T> {
|
|||
return entry != null && entry.getValue() != null;
|
||||
}
|
||||
|
||||
private boolean insert(T element) {
|
||||
private
|
||||
boolean insert(T element) {
|
||||
if (!this.entries.containsKey(element)) {
|
||||
this.head = createEntry(element, this.head);
|
||||
this.entries.put(element, this.head);
|
||||
|
@ -83,17 +89,20 @@ public abstract class AbstractConcurrentSet<T> implements Set<T> {
|
|||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
public
|
||||
int size() {
|
||||
return this.entries.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
public
|
||||
boolean isEmpty() {
|
||||
return this.head == null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean addAll(Collection<? extends T> elements) {
|
||||
public
|
||||
boolean addAll(Collection<? extends T> elements) {
|
||||
StampedLock lock = this.lock;
|
||||
|
||||
boolean changed = false;
|
||||
|
@ -116,7 +125,8 @@ public abstract class AbstractConcurrentSet<T> implements Set<T> {
|
|||
* @return TRUE if the element was successfully removed
|
||||
*/
|
||||
@Override
|
||||
public boolean remove(Object element) {
|
||||
public
|
||||
boolean remove(Object element) {
|
||||
StampedLock lock = this.lock;
|
||||
long stamp = lock.readLock();
|
||||
|
||||
|
@ -126,13 +136,15 @@ public abstract class AbstractConcurrentSet<T> implements Set<T> {
|
|||
|
||||
if (entry == null || entry.getValue() == null) {
|
||||
return false; // fast exit
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
stamp = lock.writeLock();
|
||||
|
||||
try {
|
||||
if (entry != this.head) {
|
||||
entry.remove();
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
// if it was second, now it's first
|
||||
this.head = this.head.next();
|
||||
//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
|
||||
public Object[] toArray() {
|
||||
public
|
||||
Object[] toArray() {
|
||||
return this.entries.entrySet().toArray();
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T2> T2[] toArray(T2[] a) {
|
||||
public
|
||||
<T2> T2[] toArray(T2[] a) {
|
||||
return this.entries.entrySet().toArray(a);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean containsAll(Collection<?> c) {
|
||||
public
|
||||
boolean containsAll(Collection<?> c) {
|
||||
throw new UnsupportedOperationException("Not implemented");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean removeAll(Collection<?> c) {
|
||||
public
|
||||
boolean removeAll(Collection<?> c) {
|
||||
throw new UnsupportedOperationException("Not implemented");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean retainAll(Collection<?> c) {
|
||||
public
|
||||
boolean retainAll(Collection<?> c) {
|
||||
throw new UnsupportedOperationException("Not implemented");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear() {
|
||||
public
|
||||
void clear() {
|
||||
StampedLock lock = this.lock;
|
||||
|
||||
long stamp = lock.writeLock();
|
||||
|
@ -181,7 +199,8 @@ public abstract class AbstractConcurrentSet<T> implements Set<T> {
|
|||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
public
|
||||
int hashCode() {
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
result = prime * result + (int) (this.ID ^ this.ID >>> 32);
|
||||
|
@ -189,7 +208,8 @@ public abstract class AbstractConcurrentSet<T> implements Set<T> {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
public
|
||||
boolean equals(Object obj) {
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -11,34 +11,40 @@ import java.util.Arrays;
|
|||
* @author dorkbox, llc
|
||||
* Date: 2/2/15
|
||||
*/
|
||||
public final class DeadMessage {
|
||||
public final
|
||||
class DeadMessage {
|
||||
|
||||
private final Object[] relatedMessages;
|
||||
|
||||
|
||||
public DeadMessage(Object message) {
|
||||
public
|
||||
DeadMessage(Object message) {
|
||||
this.relatedMessages = new Object[1];
|
||||
this.relatedMessages[0] = message;
|
||||
}
|
||||
|
||||
public DeadMessage(Object message1, Object message2) {
|
||||
public
|
||||
DeadMessage(Object message1, Object message2) {
|
||||
this.relatedMessages = new Object[2];
|
||||
this.relatedMessages[0] = message1;
|
||||
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[0] = message1;
|
||||
this.relatedMessages[1] = message2;
|
||||
this.relatedMessages[2] = message3;
|
||||
}
|
||||
|
||||
public DeadMessage(Object[] messages) {
|
||||
public
|
||||
DeadMessage(Object[] messages) {
|
||||
this.relatedMessages = Arrays.copyOf(messages, messages.length);
|
||||
}
|
||||
|
||||
public Object[] getMessages() {
|
||||
public
|
||||
Object[] getMessages() {
|
||||
return this.relatedMessages;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -32,7 +32,7 @@ public class HashMapTree<KEY, VALUE> {
|
|||
* can be overridden to provide a custom backing map
|
||||
*/
|
||||
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() {
|
||||
|
|
|
@ -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
|
||||
* 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.
|
||||
* <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
|
||||
* tell the difference (the message that is being sent), if it is a vararg or array.
|
||||
* <p>
|
||||
* <p>
|
||||
* BECAUSE OF THIS, we always treat the two the same
|
||||
* <p>
|
||||
* <p>
|
||||
* tell the difference (the message that is being sent), if it is a vararg or array.
|
||||
* <p/>
|
||||
* <p/>
|
||||
* BECAUSE OF THIS, we always treat the two the same
|
||||
* <p/>
|
||||
* <p/>
|
||||
*
|
||||
* @author bennidi
|
||||
* Date: 11/14/12
|
||||
* @author dorkbox, llc
|
||||
* Date: 2/2/15
|
||||
*/
|
||||
public class MessageHandler {
|
||||
public
|
||||
class MessageHandler {
|
||||
|
||||
// publish all listeners defined by the given class (includes
|
||||
// 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)
|
||||
final Method[] allMethods = ReflectionUtils.getMethods(target);
|
||||
|
@ -41,7 +43,7 @@ public class MessageHandler {
|
|||
final ArrayList<MessageHandler> finalMethods = new ArrayList<MessageHandler>(length);
|
||||
Method method;
|
||||
|
||||
for (int i=0;i<length;i++) {
|
||||
for (int i = 0; i < length; i++) {
|
||||
method = allMethods[i];
|
||||
|
||||
// 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;
|
||||
|
||||
public MessageHandler(Method handler, Handler handlerConfig) {
|
||||
public
|
||||
MessageHandler(Method handler, Handler handlerConfig) {
|
||||
super();
|
||||
|
||||
if (handler == null) {
|
||||
|
@ -92,7 +95,7 @@ public class MessageHandler {
|
|||
this.methodIndex = this.handler.getIndex(handler.getName(), handledMessages);
|
||||
|
||||
this.acceptsSubtypes = handlerConfig.acceptSubtypes();
|
||||
this.isSynchronized = ReflectionUtils.getAnnotation(handler, Synchronized.class) != null;
|
||||
this.isSynchronized = ReflectionUtils.getAnnotation(handler, Synchronized.class) != null;
|
||||
this.handledMessages = handledMessages;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
public final MethodAccess getHandler() {
|
||||
public final
|
||||
MethodAccess getHandler() {
|
||||
return this.handler;
|
||||
}
|
||||
|
||||
public final int getMethodIndex() {
|
||||
public final
|
||||
int getMethodIndex() {
|
||||
return this.methodIndex;
|
||||
}
|
||||
|
||||
public final Class<?>[] getHandledMessages() {
|
||||
public final
|
||||
Class<?>[] getHandledMessages() {
|
||||
return this.handledMessages;
|
||||
}
|
||||
|
||||
public final Class<?> getVarArgClass() {
|
||||
public final
|
||||
Class<?> getVarArgClass() {
|
||||
return this.varArgClass;
|
||||
}
|
||||
|
||||
public final boolean acceptsSubtypes() {
|
||||
public final
|
||||
boolean acceptsSubtypes() {
|
||||
return this.acceptsSubtypes;
|
||||
}
|
||||
|
||||
public final boolean acceptsVarArgs() {
|
||||
public final
|
||||
boolean acceptsVarArgs() {
|
||||
return this.varArgClass != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final int hashCode() {
|
||||
public final
|
||||
int hashCode() {
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
result = prime * result + (this.acceptsSubtypes ? 1231 : 1237);
|
||||
|
@ -143,7 +154,8 @@ public class MessageHandler {
|
|||
}
|
||||
|
||||
@Override
|
||||
public final boolean equals(Object obj) {
|
||||
public final
|
||||
boolean equals(Object obj) {
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
|
@ -164,7 +176,8 @@ public class MessageHandler {
|
|||
if (other.handler != null) {
|
||||
return false;
|
||||
}
|
||||
} else if (!this.handler.equals(other.handler)) {
|
||||
}
|
||||
else if (!this.handler.equals(other.handler)) {
|
||||
return false;
|
||||
}
|
||||
if (this.isSynchronized != other.isSynchronized) {
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
package dorkbox.util.messagebus.common;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
|
@ -10,33 +11,40 @@ import java.util.Map;
|
|||
* @author bennidi
|
||||
* 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);
|
||||
}
|
||||
|
||||
public StrongConcurrentSet(int size, float loadFactor) {
|
||||
public
|
||||
StrongConcurrentSet(int size, float 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);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<T> iterator() {
|
||||
public
|
||||
Iterator<T> iterator() {
|
||||
return new Iterator<T>() {
|
||||
private ISetEntry<T> current = StrongConcurrentSet.this.head;
|
||||
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
public
|
||||
boolean hasNext() {
|
||||
return this.current != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public T next() {
|
||||
public
|
||||
T next() {
|
||||
if (this.current == null) {
|
||||
return null;
|
||||
}
|
||||
|
@ -48,7 +56,8 @@ public class StrongConcurrentSet<T> extends AbstractConcurrentSet<T> {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void remove() {
|
||||
public
|
||||
void remove() {
|
||||
if (this.current == null) {
|
||||
return;
|
||||
}
|
||||
|
@ -60,27 +69,32 @@ public class StrongConcurrentSet<T> extends AbstractConcurrentSet<T> {
|
|||
}
|
||||
|
||||
@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);
|
||||
}
|
||||
|
||||
|
||||
public static class StrongEntry<T> extends Entry<T> {
|
||||
public static
|
||||
class StrongEntry<T> extends Entry<T> {
|
||||
|
||||
private T value;
|
||||
|
||||
private StrongEntry(T value, Entry<T> next) {
|
||||
private
|
||||
StrongEntry(T value, Entry<T> next) {
|
||||
super(next);
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
private StrongEntry(T value) {
|
||||
private
|
||||
StrongEntry(T value) {
|
||||
super();
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public T getValue() {
|
||||
public
|
||||
T getValue() {
|
||||
return this.value;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,11 +13,11 @@ public class StrongConcurrentSetV8<T> extends StrongConcurrentSet<T> {
|
|||
|
||||
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)
|
||||
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) {
|
||||
// 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));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,15 +13,18 @@ import java.util.WeakHashMap;
|
|||
* @author bennidi
|
||||
* 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>>());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<T> iterator() {
|
||||
public
|
||||
Iterator<T> iterator() {
|
||||
return new Iterator<T>() {
|
||||
|
||||
// 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
|
||||
// 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
|
||||
private void removeOrphans(){
|
||||
private
|
||||
void removeOrphans() {
|
||||
|
||||
StampedLock lock = WeakConcurrentSet.this.lock;
|
||||
long stamp = lock.writeLock();
|
||||
// final Lock writeLock = WeakConcurrentSet.this.lock.writeLock();
|
||||
// writeLock.lock();
|
||||
try{
|
||||
try {
|
||||
do {
|
||||
ISetEntry<T> orphaned = this.current;
|
||||
this.current = this.current.next();
|
||||
orphaned.remove();
|
||||
} while(this.current != null && this.current.getValue() == null);
|
||||
}
|
||||
finally {
|
||||
} while (this.current != null && this.current.getValue() == null);
|
||||
} finally {
|
||||
lock.unlockWrite(stamp);
|
||||
// writeLock.unlock();
|
||||
}
|
||||
|
@ -52,7 +55,8 @@ public class WeakConcurrentSet<T> extends AbstractConcurrentSet<T>{
|
|||
|
||||
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
public
|
||||
boolean hasNext() {
|
||||
if (this.current == null) {
|
||||
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
|
||||
removeOrphans();
|
||||
return this.current != null; // if any entry is left then it will have a value
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public T next() {
|
||||
public
|
||||
T next() {
|
||||
if (this.current == null) {
|
||||
return null;
|
||||
}
|
||||
|
@ -75,14 +81,16 @@ public class WeakConcurrentSet<T> extends AbstractConcurrentSet<T>{
|
|||
if (value == null) { // auto-removal of orphan references
|
||||
removeOrphans();
|
||||
return next();
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
this.current = this.current.next();
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove() {
|
||||
public
|
||||
void remove() {
|
||||
//throw new UnsupportedOperationException("Explicit removal of set elements is only allowed via the controlling set. Sorry!");
|
||||
if (this.current == null) {
|
||||
return;
|
||||
|
@ -95,27 +103,32 @@ public class WeakConcurrentSet<T> extends AbstractConcurrentSet<T>{
|
|||
}
|
||||
|
||||
@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);
|
||||
}
|
||||
|
||||
|
||||
public static class WeakEntry<T> extends Entry<T> {
|
||||
public static
|
||||
class WeakEntry<T> extends Entry<T> {
|
||||
|
||||
private WeakReference<T> value;
|
||||
|
||||
private WeakEntry(T value, Entry<T> next) {
|
||||
private
|
||||
WeakEntry(T value, Entry<T> next) {
|
||||
super(next);
|
||||
this.value = new WeakReference<T>(value);
|
||||
}
|
||||
|
||||
private WeakEntry(T value) {
|
||||
private
|
||||
WeakEntry(T value) {
|
||||
super();
|
||||
this.value = new WeakReference<T>(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public T getValue() {
|
||||
public
|
||||
T getValue() {
|
||||
return this.value.get();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,7 +21,6 @@ import java.util.Map;
|
|||
import java.util.NoSuchElementException;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
import java.util.concurrent.ForkJoinPool;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.concurrent.locks.LockSupport;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
|
|
@ -5,10 +5,12 @@ import java.util.concurrent.ConcurrentMap;
|
|||
/**
|
||||
*
|
||||
*/
|
||||
public class Java7Adapter extends JavaVersionAdapter {
|
||||
public
|
||||
class Java6Adapter implements MapAdapter {
|
||||
|
||||
@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);
|
||||
}
|
||||
}
|
|
@ -3,9 +3,11 @@ package dorkbox.util.messagebus.common.adapter;
|
|||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
|
||||
public class Java8Adapter extends JavaVersionAdapter {
|
||||
public
|
||||
class Java8Adapter implements MapAdapter {
|
||||
@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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,29 +1,29 @@
|
|||
package dorkbox.util.messagebus.common.adapter;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
|
||||
|
||||
|
||||
public abstract class JavaVersionAdapter {
|
||||
public
|
||||
class JavaVersionAdapter {
|
||||
|
||||
|
||||
public static final JavaVersionAdapter get;
|
||||
private static final MapAdapter get;
|
||||
|
||||
static {
|
||||
// get = new Java7Adapter();
|
||||
get = new Java8Adapter();
|
||||
|
||||
MapAdapter adapter;
|
||||
try {
|
||||
Class.forName("java.util.concurrent.locks.StampedLock");
|
||||
adapter = new Java8Adapter();
|
||||
} catch (Exception e) {
|
||||
adapter = new Java6Adapter();
|
||||
}
|
||||
|
||||
get = adapter;
|
||||
}
|
||||
|
||||
|
||||
public abstract <K, V> ConcurrentMap<K, V> concurrentMap(final int size, final float loadFactor, final int stripeSize);
|
||||
|
||||
public <K, V> Map<K, V> hashMap(final int size, final float loadFactor) {
|
||||
return new ConcurrentHashMap<K, V>(size, loadFactor, 1);
|
||||
public static
|
||||
<K, V> ConcurrentMap<K, V> concurrentMap(final int size, final float loadFactor, final int stripeSize) {
|
||||
return get.concurrentMap(size, loadFactor, stripeSize);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
package dorkbox.util.messagebus.common.adapter;
|
||||
|
||||
import java.util.concurrent.ThreadLocalRandom;
|
||||
import java.util.Random;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.locks.Condition;
|
||||
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 WMODE = 1;
|
||||
|
||||
private static final ThreadLocal<Random> randomThreadLocal = new ThreadLocal<Random>() {
|
||||
@Override
|
||||
protected
|
||||
Random initialValue() {
|
||||
return new Random();
|
||||
}
|
||||
};
|
||||
|
||||
/** Wait nodes */
|
||||
static final class WNode {
|
||||
volatile WNode prev;
|
||||
|
@ -308,6 +316,7 @@ public class StampedLock implements java.io.Serializable {
|
|||
/** extra reader count when state read count saturated */
|
||||
private transient int readerOverflow;
|
||||
|
||||
|
||||
/**
|
||||
* Creates a new lock, initially in unlocked state.
|
||||
*/
|
||||
|
@ -1004,7 +1013,7 @@ public class StampedLock implements java.io.Serializable {
|
|||
return s;
|
||||
}
|
||||
}
|
||||
else if ((ThreadLocalRandom.current().nextInt() &
|
||||
else if ((randomThreadLocal.get().nextInt() &
|
||||
OVERFLOW_YIELD_RATE) == 0) {
|
||||
Thread.yield();
|
||||
}
|
||||
|
@ -1032,7 +1041,7 @@ public class StampedLock implements java.io.Serializable {
|
|||
return next;
|
||||
}
|
||||
}
|
||||
else if ((ThreadLocalRandom.current().nextInt() &
|
||||
else if ((randomThreadLocal.get().nextInt() &
|
||||
OVERFLOW_YIELD_RATE) == 0) {
|
||||
Thread.yield();
|
||||
}
|
||||
|
@ -1084,7 +1093,7 @@ public class StampedLock implements java.io.Serializable {
|
|||
else if (spins < 0) {
|
||||
spins = m == WBIT && this.wtail == this.whead ? SPINS : 0;
|
||||
} else if (spins > 0) {
|
||||
if (ThreadLocalRandom.current().nextInt() >= 0) {
|
||||
if (randomThreadLocal.get().nextInt() >= 0) {
|
||||
--spins;
|
||||
}
|
||||
}
|
||||
|
@ -1122,7 +1131,7 @@ public class StampedLock implements java.io.Serializable {
|
|||
return ns;
|
||||
}
|
||||
}
|
||||
else if (ThreadLocalRandom.current().nextInt() >= 0 &&
|
||||
else if (randomThreadLocal.get().nextInt() >= 0 &&
|
||||
--k <= 0) {
|
||||
break;
|
||||
}
|
||||
|
@ -1198,7 +1207,7 @@ public class StampedLock implements java.io.Serializable {
|
|||
return ns;
|
||||
} else if (m >= WBIT) {
|
||||
if (spins > 0) {
|
||||
if (ThreadLocalRandom.current().nextInt() >= 0) {
|
||||
if (randomThreadLocal.get().nextInt() >= 0) {
|
||||
--spins;
|
||||
}
|
||||
}
|
||||
|
@ -1307,7 +1316,7 @@ public class StampedLock implements java.io.Serializable {
|
|||
return ns;
|
||||
}
|
||||
else if (m >= WBIT &&
|
||||
ThreadLocalRandom.current().nextInt() >= 0 && --k <= 0) {
|
||||
randomThreadLocal.get().nextInt() >= 0 && --k <= 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
* 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 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 ConcurrentMap<T, Node<T>> entries;
|
||||
|
||||
public ConcurrentSet() {
|
||||
public
|
||||
ConcurrentSet() {
|
||||
this(16, 0.75f, Runtime.getRuntime().availableProcessors());
|
||||
}
|
||||
|
||||
public ConcurrentSet(int size, float loadFactor, int stripeSize) {
|
||||
public
|
||||
ConcurrentSet(int size, float loadFactor, int stripeSize) {
|
||||
super();
|
||||
this.entries = JavaVersionAdapter.get.concurrentMap(size, loadFactor, 32);
|
||||
this.entries = JavaVersionAdapter.concurrentMap(size, loadFactor, 32);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean add(T element) {
|
||||
public
|
||||
boolean add(T element) {
|
||||
if (element == null) {
|
||||
return false;
|
||||
}
|
||||
|
@ -54,7 +58,8 @@ public class ConcurrentSet<T> extends ConcurrentLinkedQueue2<T> {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean contains(Object element) {
|
||||
public
|
||||
boolean contains(Object element) {
|
||||
if (element == null) {
|
||||
return false;
|
||||
}
|
||||
|
@ -72,12 +77,14 @@ public class ConcurrentSet<T> extends ConcurrentLinkedQueue2<T> {
|
|||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
public
|
||||
int size() {
|
||||
return this.entries.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
public
|
||||
boolean isEmpty() {
|
||||
return super.isEmpty();
|
||||
}
|
||||
|
||||
|
@ -85,7 +92,8 @@ public class ConcurrentSet<T> extends ConcurrentLinkedQueue2<T> {
|
|||
* @return TRUE if the element was successfully removed
|
||||
*/
|
||||
@Override
|
||||
public boolean remove(Object element) {
|
||||
public
|
||||
boolean remove(Object element) {
|
||||
while (this.entries.get(element) == this.IN_PROGRESS_MARKER) {
|
||||
; // data race
|
||||
}
|
||||
|
@ -113,11 +121,13 @@ public class ConcurrentSet<T> extends ConcurrentLinkedQueue2<T> {
|
|||
}
|
||||
|
||||
@Override
|
||||
public Iterator<T> iterator() {
|
||||
public
|
||||
Iterator<T> iterator() {
|
||||
return new Itr2();
|
||||
}
|
||||
|
||||
private class Itr2 implements Iterator<T> {
|
||||
private
|
||||
class Itr2 implements Iterator<T> {
|
||||
/**
|
||||
* 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
|
||||
* next(), or null if no such.
|
||||
*/
|
||||
private T advance() {
|
||||
private
|
||||
T advance() {
|
||||
this.lastRet = this.nextNode; // for removing items via iterator
|
||||
T nextItem = this.nextItem;
|
||||
|
||||
|
@ -152,12 +163,13 @@ public class ConcurrentSet<T> extends ConcurrentLinkedQueue2<T> {
|
|||
if (this.nextNode == null) {
|
||||
p = first();
|
||||
pred = null;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
pred = this.nextNode;
|
||||
p = succ(this.nextNode);
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
for (; ; ) {
|
||||
if (p == null) {
|
||||
this.nextNode = null;
|
||||
this.nextItem = null;
|
||||
|
@ -169,7 +181,8 @@ public class ConcurrentSet<T> extends ConcurrentLinkedQueue2<T> {
|
|||
this.nextNode = p;
|
||||
this.nextItem = item;
|
||||
return nextItem;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
// skip over nulls
|
||||
Node<T> next = succ(p);
|
||||
if (pred != null && next != null) {
|
||||
|
@ -183,12 +196,14 @@ public class ConcurrentSet<T> extends ConcurrentLinkedQueue2<T> {
|
|||
|
||||
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
public
|
||||
boolean hasNext() {
|
||||
return this.nextNode != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public T next() {
|
||||
public
|
||||
T next() {
|
||||
if (this.nextNode == null) {
|
||||
throw new NoSuchElementException();
|
||||
}
|
||||
|
@ -196,7 +211,8 @@ public class ConcurrentSet<T> extends ConcurrentLinkedQueue2<T> {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void remove() {
|
||||
public
|
||||
void remove() {
|
||||
Node<T> l = this.lastRet;
|
||||
if (l == null) {
|
||||
throw new IllegalStateException();
|
||||
|
@ -220,37 +236,44 @@ public class ConcurrentSet<T> extends ConcurrentLinkedQueue2<T> {
|
|||
}
|
||||
|
||||
@Override
|
||||
public Object[] toArray() {
|
||||
public
|
||||
Object[] toArray() {
|
||||
return this.entries.keySet().toArray();
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T[] toArray(T[] a) {
|
||||
public
|
||||
<T> T[] toArray(T[] a) {
|
||||
return this.entries.keySet().toArray(a);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean containsAll(Collection<?> c) {
|
||||
public
|
||||
boolean containsAll(Collection<?> c) {
|
||||
throw new UnsupportedOperationException("Not implemented");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean removeAll(Collection<?> c) {
|
||||
public
|
||||
boolean removeAll(Collection<?> c) {
|
||||
throw new UnsupportedOperationException("Not implemented");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean retainAll(Collection<?> c) {
|
||||
public
|
||||
boolean retainAll(Collection<?> c) {
|
||||
throw new UnsupportedOperationException("Not implemented");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear() {
|
||||
public
|
||||
void clear() {
|
||||
super.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
public
|
||||
int hashCode() {
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
result = prime * result + (int) (this.ID ^ this.ID >>> 32);
|
||||
|
@ -258,7 +281,8 @@ public class ConcurrentSet<T> extends ConcurrentLinkedQueue2<T> {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
public
|
||||
boolean equals(Object obj) {
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -10,14 +10,15 @@ import java.util.concurrent.atomic.AtomicInteger;
|
|||
* @author dorkbox, llc
|
||||
* 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
|
||||
* 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)
|
||||
* Setting the size MAY or MAY NOT have any effect!!!
|
||||
* <p>
|
||||
* <p/>
|
||||
* Stack size must be specified in bytes. Default is 8k
|
||||
*/
|
||||
private static final long stackSizeForThreads;
|
||||
|
@ -67,13 +68,15 @@ public class NamedThreadFactory implements ThreadFactory {
|
|||
private final ThreadGroup group;
|
||||
private final String groupName;
|
||||
|
||||
public NamedThreadFactory(String groupName) {
|
||||
public
|
||||
NamedThreadFactory(String groupName) {
|
||||
this.groupName = groupName;
|
||||
this.group = new ThreadGroup(groupName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Thread newThread(Runnable r) {
|
||||
public
|
||||
Thread newThread(Runnable r) {
|
||||
StringBuilder stringBuilder = new StringBuilder();
|
||||
stringBuilder.append(this.groupName);
|
||||
stringBuilder.append('-');
|
||||
|
@ -83,7 +86,8 @@ public class NamedThreadFactory implements ThreadFactory {
|
|||
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
|
||||
// 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)
|
||||
|
|
|
@ -10,29 +10,37 @@ import com.esotericsoftware.reflectasm.MethodAccess;
|
|||
* @author dorkbox, llc
|
||||
* Date: 2/2/15
|
||||
*/
|
||||
public class ReflectiveHandlerInvocation implements IHandlerInvocation {
|
||||
public
|
||||
class ReflectiveHandlerInvocation implements IHandlerInvocation {
|
||||
|
||||
public ReflectiveHandlerInvocation() {
|
||||
public
|
||||
ReflectiveHandlerInvocation() {
|
||||
super();
|
||||
}
|
||||
|
||||
@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);
|
||||
}
|
||||
|
||||
@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);
|
||||
}
|
||||
|
||||
@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);
|
||||
}
|
||||
|
||||
@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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,37 +10,45 @@ import com.esotericsoftware.reflectasm.MethodAccess;
|
|||
* @author dorkbox, llc
|
||||
* Date: 2/2/15
|
||||
*/
|
||||
public class SynchronizedHandlerInvocation implements IHandlerInvocation {
|
||||
public
|
||||
class SynchronizedHandlerInvocation implements IHandlerInvocation {
|
||||
|
||||
private IHandlerInvocation delegate;
|
||||
|
||||
public SynchronizedHandlerInvocation(IHandlerInvocation delegate) {
|
||||
public
|
||||
SynchronizedHandlerInvocation(IHandlerInvocation delegate) {
|
||||
this.delegate = delegate;
|
||||
}
|
||||
|
||||
@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) {
|
||||
this.delegate.invoke(listener, handler, methodIndex, message);
|
||||
}
|
||||
}
|
||||
|
||||
@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) {
|
||||
this.delegate.invoke(listener, handler, methodIndex, message1, message2);
|
||||
}
|
||||
}
|
||||
|
||||
@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) {
|
||||
this.delegate.invoke(listener, handler, methodIndex, message1, message2, message3);
|
||||
}
|
||||
}
|
||||
|
||||
@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) {
|
||||
this.delegate.invoke(listener, handler, methodIndex, messages);
|
||||
}
|
||||
|
|
|
@ -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" +
|
||||
"Publication error handlers can be added by bus.getErrorHandler().addErrorHandler()\n" +
|
||||
"Falling back to console logger.";
|
||||
private static final String ERROR_HANDLER_MSG =
|
||||
"INFO: No error handler has been configured to handle exceptions during publication.\n" +
|
||||
"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
|
||||
private final Collection<IPublicationErrorHandler> errorHandlers = new ArrayDeque<IPublicationErrorHandler>();
|
||||
|
||||
|
||||
public DefaultErrorHandler() {
|
||||
public
|
||||
DefaultErrorHandler() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void addErrorHandler(IPublicationErrorHandler handler) {
|
||||
public final
|
||||
void addErrorHandler(IPublicationErrorHandler handler) {
|
||||
synchronized (this.errorHandlers) {
|
||||
this.errorHandlers.add(handler);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void handlePublicationError(PublicationError error) {
|
||||
public final
|
||||
void handlePublicationError(PublicationError error) {
|
||||
synchronized (this.errorHandlers) {
|
||||
for (IPublicationErrorHandler errorHandler : this.errorHandlers) {
|
||||
errorHandler.handleError(error);
|
||||
|
@ -36,7 +41,8 @@ public class DefaultErrorHandler implements ErrorHandlingSupport {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void handleError(final String error, final Class<?> listenerClass) {
|
||||
public
|
||||
void handleError(final String error, final Class<?> listenerClass) {
|
||||
synchronized (this.errorHandlers) {
|
||||
for (IPublicationErrorHandler errorHandler : this.errorHandlers) {
|
||||
errorHandler.handleError(error, listenerClass);
|
||||
|
@ -45,7 +51,8 @@ public class DefaultErrorHandler implements ErrorHandlingSupport {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void start() {
|
||||
public
|
||||
void start() {
|
||||
synchronized (this.errorHandlers) {
|
||||
if (this.errorHandlers.isEmpty()) {
|
||||
this.errorHandlers.add(new IPublicationErrorHandler.ConsoleLogger());
|
||||
|
|
|
@ -5,7 +5,8 @@ package dorkbox.util.messagebus.error;
|
|||
* @author dorkbox, llc
|
||||
* 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,
|
||||
|
|
|
@ -5,12 +5,13 @@ package dorkbox.util.messagebus.error;
|
|||
* error occurs during message publication.
|
||||
* A handler might fail with an exception, not be accessible because of the presence
|
||||
* of a security manager or other reasons might lead to failures during the message publication process.
|
||||
* <p>
|
||||
* <p/>
|
||||
*
|
||||
* @author bennidi
|
||||
* Date: 2/22/12
|
||||
*/
|
||||
public interface IPublicationErrorHandler {
|
||||
public
|
||||
interface IPublicationErrorHandler {
|
||||
|
||||
/**
|
||||
* Handle the given publication error.
|
||||
|
@ -22,7 +23,7 @@ public interface IPublicationErrorHandler {
|
|||
/**
|
||||
* Handle the given publication error.
|
||||
*
|
||||
* @param error The PublicationError to handle.
|
||||
* @param error The PublicationError to handle.
|
||||
* @param 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
|
||||
* print the stack trace if available.
|
||||
*/
|
||||
final class ConsoleLogger implements IPublicationErrorHandler {
|
||||
final
|
||||
class ConsoleLogger implements IPublicationErrorHandler {
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public void handleError(final PublicationError error) {
|
||||
public
|
||||
void handleError(final PublicationError error) {
|
||||
// Printout the error itself
|
||||
System.out.println(error);
|
||||
|
||||
|
@ -51,7 +54,8 @@ public interface IPublicationErrorHandler {
|
|||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public void handleError(final String error, final Class<?> listenerClass) {
|
||||
public
|
||||
void handleError(final String error, final Class<?> listenerClass) {
|
||||
// Printout the error itself
|
||||
System.out.println(new StringBuilder().append(error).append(": ").append(listenerClass.getSimpleName()).toString());
|
||||
}
|
||||
|
|
|
@ -6,21 +6,26 @@ package dorkbox.util.messagebus.error;
|
|||
* @author bennidi
|
||||
* Date: 3/29/13
|
||||
*/
|
||||
public class MessageBusException extends Exception {
|
||||
public
|
||||
class MessageBusException extends Exception {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public MessageBusException() {
|
||||
public
|
||||
MessageBusException() {
|
||||
}
|
||||
|
||||
public MessageBusException(String message) {
|
||||
public
|
||||
MessageBusException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public MessageBusException(String message, Throwable cause) {
|
||||
public
|
||||
MessageBusException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
|
||||
public MessageBusException(Throwable cause) {
|
||||
public
|
||||
MessageBusException(Throwable cause) {
|
||||
super(cause);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,7 +14,8 @@ import java.util.Arrays;
|
|||
* @author dorkbox, llc
|
||||
* Date: 2/2/15
|
||||
*/
|
||||
public class PublicationError {
|
||||
public
|
||||
class PublicationError {
|
||||
|
||||
// Internal state
|
||||
private Throwable cause;
|
||||
|
@ -25,14 +26,16 @@ public class PublicationError {
|
|||
/**
|
||||
* Default constructor.
|
||||
*/
|
||||
public PublicationError() {
|
||||
public
|
||||
PublicationError() {
|
||||
super();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The Throwable giving rise to this PublicationError.
|
||||
*/
|
||||
public Throwable getCause() {
|
||||
public
|
||||
Throwable getCause() {
|
||||
return this.cause;
|
||||
}
|
||||
|
||||
|
@ -42,32 +45,38 @@ public class PublicationError {
|
|||
* @param cause A Throwable which gave rise to this PublicationError.
|
||||
* @return This PublicationError.
|
||||
*/
|
||||
public PublicationError setCause(Throwable cause) {
|
||||
public
|
||||
PublicationError setCause(Throwable cause) {
|
||||
this.cause = cause;
|
||||
return this;
|
||||
}
|
||||
|
||||
public String getMessage() {
|
||||
public
|
||||
String getMessage() {
|
||||
return this.message;
|
||||
}
|
||||
|
||||
public PublicationError setMessage(String message) {
|
||||
public
|
||||
PublicationError setMessage(String message) {
|
||||
this.message = message;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Object[] getPublishedObject() {
|
||||
public
|
||||
Object[] getPublishedObject() {
|
||||
return this.publishedObjects;
|
||||
}
|
||||
|
||||
public PublicationError setPublishedObject(Object publishedObject) {
|
||||
public
|
||||
PublicationError setPublishedObject(Object publishedObject) {
|
||||
this.publishedObjects = new Object[1];
|
||||
this.publishedObjects[0] = publishedObject;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public PublicationError setPublishedObject(Object publishedObject1, Object publishedObject2) {
|
||||
public
|
||||
PublicationError setPublishedObject(Object publishedObject1, Object publishedObject2) {
|
||||
this.publishedObjects = new Object[2];
|
||||
this.publishedObjects[0] = publishedObject1;
|
||||
this.publishedObjects[1] = publishedObject2;
|
||||
|
@ -75,7 +84,8 @@ public class PublicationError {
|
|||
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[0] = publishedObject1;
|
||||
this.publishedObjects[1] = publishedObject2;
|
||||
|
@ -88,15 +98,16 @@ public class PublicationError {
|
|||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
public
|
||||
String toString() {
|
||||
String newLine = System.getProperty("line.separator");
|
||||
return "PublicationError{" +
|
||||
newLine +
|
||||
"\tcause=" + this.cause +
|
||||
newLine +
|
||||
"\tmessage='" + this.message + '\'' +
|
||||
newLine +
|
||||
"\tpublishedObject=" + Arrays.deepToString(this.publishedObjects) +
|
||||
'}';
|
||||
newLine +
|
||||
"\tcause=" + this.cause +
|
||||
newLine +
|
||||
"\tmessage='" + this.message + '\'' +
|
||||
newLine +
|
||||
"\tpublishedObject=" + Arrays.deepToString(this.publishedObjects) +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,7 +11,8 @@ import dorkbox.util.messagebus.utils.VarArgUtils;
|
|||
import java.lang.reflect.Array;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
public class PublisherAll_MultiArg implements Publisher {
|
||||
public
|
||||
class PublisherAll_MultiArg implements Publisher {
|
||||
private final ErrorHandlingSupport errorHandler;
|
||||
|
||||
private final Subscriber subscriber;
|
||||
|
@ -20,7 +21,8 @@ public class PublisherAll_MultiArg implements Publisher {
|
|||
private final AtomicBoolean varArgPossibility;
|
||||
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.subscriber = subscriber;
|
||||
this.lock = lock;
|
||||
|
@ -30,7 +32,8 @@ public class PublisherAll_MultiArg implements Publisher {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void publish(final Object message1) {
|
||||
public
|
||||
void publish(final Object message1) {
|
||||
try {
|
||||
final Class<?> messageClass = message1.getClass();
|
||||
final boolean isArray = messageClass.isArray();
|
||||
|
@ -117,13 +120,14 @@ public class PublisherAll_MultiArg implements Publisher {
|
|||
}
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
errorHandler.handlePublicationError(new PublicationError().setMessage("Error during invocation of message handler.").setCause(e)
|
||||
.setPublishedObject(message1));
|
||||
errorHandler.handlePublicationError(new PublicationError().setMessage("Error during invocation of message handler.").setCause(
|
||||
e).setPublishedObject(message1));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void publish(final Object message1, final Object message2) {
|
||||
public
|
||||
void publish(final Object message1, final Object message2) {
|
||||
try {
|
||||
final Class<?> messageClass1 = message1.getClass();
|
||||
final Class<?> messageClass2 = message2.getClass();
|
||||
|
@ -215,13 +219,14 @@ public class PublisherAll_MultiArg implements Publisher {
|
|||
}
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
errorHandler.handlePublicationError(new PublicationError().setMessage("Error during invocation of message handler.").setCause(e)
|
||||
.setPublishedObject(message1, message2));
|
||||
errorHandler.handlePublicationError(new PublicationError().setMessage("Error during invocation of message handler.").setCause(
|
||||
e).setPublishedObject(message1, message2));
|
||||
}
|
||||
}
|
||||
|
||||
@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 {
|
||||
final Class<?> messageClass1 = message1.getClass();
|
||||
final Class<?> messageClass2 = message2.getClass();
|
||||
|
@ -319,13 +324,14 @@ public class PublisherAll_MultiArg implements Publisher {
|
|||
}
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
errorHandler.handlePublicationError(new PublicationError().setMessage("Error during invocation of message handler.").setCause(e)
|
||||
.setPublishedObject(message1, message2, message3));
|
||||
errorHandler.handlePublicationError(new PublicationError().setMessage("Error during invocation of message handler.").setCause(
|
||||
e).setPublishedObject(message1, message2, message3));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void publish(final Object[] messages) {
|
||||
public
|
||||
void publish(final Object[] messages) {
|
||||
publish((Object) messages);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,20 +9,22 @@ import dorkbox.util.messagebus.subscription.Subscription;
|
|||
|
||||
import java.util.Arrays;
|
||||
|
||||
public class PublisherExactWithSuperTypes_FirstArg implements Publisher {
|
||||
public
|
||||
class PublisherExactWithSuperTypes_FirstArg implements Publisher {
|
||||
private final ErrorHandlingSupport errorHandler;
|
||||
private final Subscriber subscriber;
|
||||
private final StampedLock lock;
|
||||
|
||||
public PublisherExactWithSuperTypes_FirstArg(final ErrorHandlingSupport errorHandler, final Subscriber subscriber,
|
||||
final StampedLock lock) {
|
||||
public
|
||||
PublisherExactWithSuperTypes_FirstArg(final ErrorHandlingSupport errorHandler, final Subscriber subscriber, final StampedLock lock) {
|
||||
this.errorHandler = errorHandler;
|
||||
this.subscriber = subscriber;
|
||||
this.lock = lock;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void publish(final Object message1) {
|
||||
public
|
||||
void publish(final Object message1) {
|
||||
try {
|
||||
final Class<?> messageClass = message1.getClass();
|
||||
|
||||
|
@ -61,13 +63,14 @@ public class PublisherExactWithSuperTypes_FirstArg implements Publisher {
|
|||
}
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
errorHandler.handlePublicationError(new PublicationError().setMessage("Error during invocation of message handler.").setCause(e)
|
||||
.setPublishedObject(message1));
|
||||
errorHandler.handlePublicationError(new PublicationError().setMessage("Error during invocation of message handler.").setCause(
|
||||
e).setPublishedObject(message1));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void publish(final Object message1, final Object message2) {
|
||||
public
|
||||
void publish(final Object message1, final Object message2) {
|
||||
try {
|
||||
final Class<?> messageClass = message1.getClass();
|
||||
|
||||
|
@ -106,13 +109,14 @@ public class PublisherExactWithSuperTypes_FirstArg implements Publisher {
|
|||
}
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
errorHandler.handlePublicationError(new PublicationError().setMessage("Error during invocation of message handler.").setCause(e)
|
||||
.setPublishedObject(message1, message2));
|
||||
errorHandler.handlePublicationError(new PublicationError().setMessage("Error during invocation of message handler.").setCause(
|
||||
e).setPublishedObject(message1, message2));
|
||||
}
|
||||
}
|
||||
|
||||
@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 {
|
||||
final Class<?> messageClass = message1.getClass();
|
||||
|
||||
|
@ -151,13 +155,14 @@ public class PublisherExactWithSuperTypes_FirstArg implements Publisher {
|
|||
}
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
errorHandler.handlePublicationError(new PublicationError().setMessage("Error during invocation of message handler.").setCause(e)
|
||||
.setPublishedObject(message1, message2, message3));
|
||||
errorHandler.handlePublicationError(new PublicationError().setMessage("Error during invocation of message handler.").setCause(
|
||||
e).setPublishedObject(message1, message2, message3));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void publish(final Object[] messages) {
|
||||
public
|
||||
void publish(final Object[] messages) {
|
||||
try {
|
||||
final Object message1 = messages[0];
|
||||
final Class<?> messageClass = message1.getClass();
|
||||
|
@ -199,8 +204,8 @@ public class PublisherExactWithSuperTypes_FirstArg implements Publisher {
|
|||
}
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
errorHandler.handlePublicationError(new PublicationError().setMessage("Error during invocation of message handler.").setCause(e)
|
||||
.setPublishedObject(messages));
|
||||
errorHandler.handlePublicationError(new PublicationError().setMessage("Error during invocation of message handler.").setCause(
|
||||
e).setPublishedObject(messages));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,20 +7,22 @@ import dorkbox.util.messagebus.error.PublicationError;
|
|||
import dorkbox.util.messagebus.subscription.Subscriber;
|
||||
import dorkbox.util.messagebus.subscription.Subscription;
|
||||
|
||||
public class PublisherExactWithSuperTypes_MultiArg implements Publisher {
|
||||
public
|
||||
class PublisherExactWithSuperTypes_MultiArg implements Publisher {
|
||||
private final ErrorHandlingSupport errorHandler;
|
||||
private final Subscriber subscriber;
|
||||
private final StampedLock lock;
|
||||
|
||||
public PublisherExactWithSuperTypes_MultiArg(final ErrorHandlingSupport errorHandler, final Subscriber subscriber,
|
||||
final StampedLock lock) {
|
||||
public
|
||||
PublisherExactWithSuperTypes_MultiArg(final ErrorHandlingSupport errorHandler, final Subscriber subscriber, final StampedLock lock) {
|
||||
this.errorHandler = errorHandler;
|
||||
this.subscriber = subscriber;
|
||||
this.lock = lock;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void publish(final Object message1) {
|
||||
public
|
||||
void publish(final Object message1) {
|
||||
try {
|
||||
final Class<?> messageClass = message1.getClass();
|
||||
|
||||
|
@ -54,13 +56,14 @@ public class PublisherExactWithSuperTypes_MultiArg implements Publisher {
|
|||
}
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
errorHandler.handlePublicationError(new PublicationError().setMessage("Error during invocation of message handler.").setCause(e)
|
||||
.setPublishedObject(message1));
|
||||
errorHandler.handlePublicationError(new PublicationError().setMessage("Error during invocation of message handler.").setCause(
|
||||
e).setPublishedObject(message1));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void publish(final Object message1, final Object message2) {
|
||||
public
|
||||
void publish(final Object message1, final Object message2) {
|
||||
try {
|
||||
final Class<?> messageClass1 = message1.getClass();
|
||||
final Class<?> messageClass2 = message2.getClass();
|
||||
|
@ -95,13 +98,14 @@ public class PublisherExactWithSuperTypes_MultiArg implements Publisher {
|
|||
}
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
errorHandler.handlePublicationError(new PublicationError().setMessage("Error during invocation of message handler.").setCause(e)
|
||||
.setPublishedObject(message1, message2));
|
||||
errorHandler.handlePublicationError(new PublicationError().setMessage("Error during invocation of message handler.").setCause(
|
||||
e).setPublishedObject(message1, message2));
|
||||
}
|
||||
}
|
||||
|
||||
@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 {
|
||||
final Class<?> messageClass1 = message1.getClass();
|
||||
final Class<?> messageClass2 = message2.getClass();
|
||||
|
@ -110,7 +114,8 @@ public class PublisherExactWithSuperTypes_MultiArg implements Publisher {
|
|||
|
||||
final StampedLock lock = this.lock;
|
||||
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);
|
||||
|
||||
// Run subscriptions
|
||||
|
@ -138,13 +143,14 @@ public class PublisherExactWithSuperTypes_MultiArg implements Publisher {
|
|||
}
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
errorHandler.handlePublicationError(new PublicationError().setMessage("Error during invocation of message handler.").setCause(e)
|
||||
.setPublishedObject(message1, message2, message3));
|
||||
errorHandler.handlePublicationError(new PublicationError().setMessage("Error during invocation of message handler.").setCause(
|
||||
e).setPublishedObject(message1, message2, message3));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void publish(final Object[] messages) {
|
||||
public
|
||||
void publish(final Object[] messages) {
|
||||
publish((Object) messages);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,19 +7,22 @@ import dorkbox.util.messagebus.error.PublicationError;
|
|||
import dorkbox.util.messagebus.subscription.Subscriber;
|
||||
import dorkbox.util.messagebus.subscription.Subscription;
|
||||
|
||||
public class PublisherExact_FirstArg implements Publisher {
|
||||
public
|
||||
class PublisherExact_FirstArg implements Publisher {
|
||||
private final ErrorHandlingSupport errorHandler;
|
||||
private final Subscriber subscriber;
|
||||
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.subscriber = subscriber;
|
||||
this.lock = lock;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void publish(final Object message1) {
|
||||
public
|
||||
void publish(final Object message1) {
|
||||
try {
|
||||
final Class<?> messageClass = message1.getClass();
|
||||
|
||||
|
@ -58,13 +61,14 @@ public class PublisherExact_FirstArg implements Publisher {
|
|||
}
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
errorHandler.handlePublicationError(new PublicationError().setMessage("Error during invocation of message handler.").setCause(e)
|
||||
.setPublishedObject(message1));
|
||||
errorHandler.handlePublicationError(new PublicationError().setMessage("Error during invocation of message handler.").setCause(
|
||||
e).setPublishedObject(message1));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void publish(final Object message1, final Object message2) {
|
||||
public
|
||||
void publish(final Object message1, final Object message2) {
|
||||
try {
|
||||
final Class<?> messageClass = message1.getClass();
|
||||
|
||||
|
@ -103,13 +107,14 @@ public class PublisherExact_FirstArg implements Publisher {
|
|||
}
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
errorHandler.handlePublicationError(new PublicationError().setMessage("Error during invocation of message handler.").setCause(e)
|
||||
.setPublishedObject(message1, message2));
|
||||
errorHandler.handlePublicationError(new PublicationError().setMessage("Error during invocation of message handler.").setCause(
|
||||
e).setPublishedObject(message1, message2));
|
||||
}
|
||||
}
|
||||
|
||||
@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 {
|
||||
final Class<?> messageClass = message1.getClass();
|
||||
|
||||
|
@ -148,13 +153,14 @@ public class PublisherExact_FirstArg implements Publisher {
|
|||
}
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
errorHandler.handlePublicationError(new PublicationError().setMessage("Error during invocation of message handler.").setCause(e)
|
||||
.setPublishedObject(message1, message2, message3));
|
||||
errorHandler.handlePublicationError(new PublicationError().setMessage("Error during invocation of message handler.").setCause(
|
||||
e).setPublishedObject(message1, message2, message3));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void publish(final Object[] messages) {
|
||||
public
|
||||
void publish(final Object[] messages) {
|
||||
try {
|
||||
final Class<?> messageClass = messages[0].getClass();
|
||||
final int length = messages.length;
|
||||
|
@ -194,8 +200,8 @@ public class PublisherExact_FirstArg implements Publisher {
|
|||
}
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
errorHandler.handlePublicationError(new PublicationError().setMessage("Error during invocation of message handler.").setCause(e)
|
||||
.setPublishedObject(messages));
|
||||
errorHandler.handlePublicationError(new PublicationError().setMessage("Error during invocation of message handler.").setCause(
|
||||
e).setPublishedObject(messages));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,19 +7,22 @@ import dorkbox.util.messagebus.error.PublicationError;
|
|||
import dorkbox.util.messagebus.subscription.Subscriber;
|
||||
import dorkbox.util.messagebus.subscription.Subscription;
|
||||
|
||||
public class PublisherExact_MultiArg implements Publisher {
|
||||
public
|
||||
class PublisherExact_MultiArg implements Publisher {
|
||||
private final ErrorHandlingSupport errorHandler;
|
||||
private final Subscriber subscriber;
|
||||
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.subscriber = subscriber;
|
||||
this.lock = lock;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void publish(final Object message1) {
|
||||
public
|
||||
void publish(final Object message1) {
|
||||
try {
|
||||
final Class<?> messageClass = message1.getClass();
|
||||
|
||||
|
@ -53,13 +56,14 @@ public class PublisherExact_MultiArg implements Publisher {
|
|||
}
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
errorHandler.handlePublicationError(new PublicationError().setMessage("Error during invocation of message handler.").setCause(e)
|
||||
.setPublishedObject(message1));
|
||||
errorHandler.handlePublicationError(new PublicationError().setMessage("Error during invocation of message handler.").setCause(
|
||||
e).setPublishedObject(message1));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void publish(final Object message1, final Object message2) {
|
||||
public
|
||||
void publish(final Object message1, final Object message2) {
|
||||
try {
|
||||
final Class<?> messageClass1 = message1.getClass();
|
||||
final Class<?> messageClass2 = message2.getClass();
|
||||
|
@ -94,13 +98,14 @@ public class PublisherExact_MultiArg implements Publisher {
|
|||
}
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
errorHandler.handlePublicationError(new PublicationError().setMessage("Error during invocation of message handler.").setCause(e)
|
||||
.setPublishedObject(message1, message2));
|
||||
errorHandler.handlePublicationError(new PublicationError().setMessage("Error during invocation of message handler.").setCause(
|
||||
e).setPublishedObject(message1, message2));
|
||||
}
|
||||
}
|
||||
|
||||
@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 {
|
||||
final Class<?> messageClass1 = message1.getClass();
|
||||
final Class<?> messageClass2 = message2.getClass();
|
||||
|
@ -136,13 +141,14 @@ public class PublisherExact_MultiArg implements Publisher {
|
|||
}
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
errorHandler.handlePublicationError(new PublicationError().setMessage("Error during invocation of message handler.").setCause(e)
|
||||
.setPublishedObject(message1, message2, message3));
|
||||
errorHandler.handlePublicationError(new PublicationError().setMessage("Error during invocation of message handler.").setCause(
|
||||
e).setPublishedObject(message1, message2, message3));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void publish(final Object[] messages) {
|
||||
public
|
||||
void publish(final Object[] messages) {
|
||||
publish((Object) messages);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -33,7 +33,7 @@ public class FirstArgSubscriber implements Subscriber {
|
|||
this.errorHandler = errorHandler;
|
||||
|
||||
// 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
|
||||
|
|
|
@ -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
|
||||
*/
|
||||
public class MultiArgSubscriber implements Subscriber {
|
||||
public
|
||||
class MultiArgSubscriber implements Subscriber {
|
||||
|
||||
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)
|
||||
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.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.subUtils = new SubscriptionUtils(classUtils, Subscriber.LOAD_FACTOR);
|
||||
|
@ -45,17 +47,20 @@ public class MultiArgSubscriber implements Subscriber {
|
|||
}
|
||||
|
||||
@Override
|
||||
public AtomicBoolean getVarArgPossibility() {
|
||||
public
|
||||
AtomicBoolean getVarArgPossibility() {
|
||||
return varArgPossibility;
|
||||
}
|
||||
|
||||
@Override
|
||||
public VarArgUtils getVarArgUtils() {
|
||||
public
|
||||
VarArgUtils getVarArgUtils() {
|
||||
return varArgUtils;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear() {
|
||||
public
|
||||
void clear() {
|
||||
this.subUtils.clear();
|
||||
this.varArgUtils.clear();
|
||||
}
|
||||
|
@ -63,10 +68,10 @@ public class MultiArgSubscriber implements Subscriber {
|
|||
// inside a write lock
|
||||
// add this subscription to each of the handled types
|
||||
// to activate this sub for publication
|
||||
private void registerMulti(final Subscription subscription, final Class<?> listenerClass,
|
||||
final Map<Class<?>, ArrayList<Subscription>> subsPerMessageSingle,
|
||||
final HashMapTree<Class<?>, ArrayList<Subscription>> subsPerMessageMulti,
|
||||
final AtomicBoolean varArgPossibility) {
|
||||
private
|
||||
void registerMulti(final Subscription subscription, final Class<?> listenerClass,
|
||||
final Map<Class<?>, ArrayList<Subscription>> subsPerMessageSingle,
|
||||
final HashMapTree<Class<?>, ArrayList<Subscription>> subsPerMessageMulti, final AtomicBoolean varArgPossibility) {
|
||||
|
||||
final MessageHandler handler = subscription.getHandler();
|
||||
final Class<?>[] messageHandlerTypes = handler.getHandledMessages();
|
||||
|
@ -131,7 +136,8 @@ public class MultiArgSubscriber implements Subscriber {
|
|||
}
|
||||
|
||||
@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 HashMapTree<Class<?>, ArrayList<Subscription>> subsPerMessageMulti = this.subscriptionsPerMessageMulti;
|
||||
|
@ -149,7 +155,8 @@ public class MultiArgSubscriber implements Subscriber {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void shutdown() {
|
||||
public
|
||||
void shutdown() {
|
||||
this.subscriptionsPerMessageSingle.clear();
|
||||
this.subscriptionsPerMessageMulti.clear();
|
||||
|
||||
|
@ -157,24 +164,27 @@ public class MultiArgSubscriber implements Subscriber {
|
|||
}
|
||||
|
||||
@Override
|
||||
public ArrayList<Subscription> getExactAsArray(final Class<?> messageClass) {
|
||||
public
|
||||
ArrayList<Subscription> getExactAsArray(final Class<?> messageClass) {
|
||||
return subscriptionsPerMessageSingle.get(messageClass);
|
||||
}
|
||||
|
||||
@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);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ArrayList<Subscription> getExactAsArray(final Class<?> messageClass1, final Class<?> messageClass2,
|
||||
final Class<?> messageClass3) {
|
||||
public
|
||||
ArrayList<Subscription> getExactAsArray(final Class<?> messageClass1, final Class<?> messageClass2, final Class<?> messageClass3) {
|
||||
return subscriptionsPerMessageMulti.get(messageClass1, messageClass2, messageClass3);
|
||||
}
|
||||
|
||||
// can return null
|
||||
@Override
|
||||
public Subscription[] getExactAndSuper(final Class<?> messageClass) {
|
||||
public
|
||||
Subscription[] getExactAndSuper(final Class<?> messageClass) {
|
||||
ArrayList<Subscription> collection = getExactAsArray(messageClass); // can return null
|
||||
|
||||
// now publish superClasses
|
||||
|
@ -203,7 +213,8 @@ public class MultiArgSubscriber implements Subscriber {
|
|||
|
||||
// can return null
|
||||
@Override
|
||||
public Subscription[] getExact(final Class<?> messageClass) {
|
||||
public
|
||||
Subscription[] getExact(final Class<?> messageClass) {
|
||||
final ArrayList<Subscription> collection = getExactAsArray(messageClass);
|
||||
|
||||
if (collection != null) {
|
||||
|
@ -218,7 +229,8 @@ public class MultiArgSubscriber implements Subscriber {
|
|||
|
||||
// can return null
|
||||
@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);
|
||||
|
||||
if (collection != null) {
|
||||
|
@ -233,7 +245,8 @@ public class MultiArgSubscriber implements Subscriber {
|
|||
|
||||
// can return null
|
||||
@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);
|
||||
|
||||
|
@ -251,7 +264,8 @@ public class MultiArgSubscriber implements Subscriber {
|
|||
|
||||
// can return null
|
||||
@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
|
||||
|
||||
// now publish superClasses
|
||||
|
@ -281,7 +295,8 @@ public class MultiArgSubscriber implements Subscriber {
|
|||
|
||||
// can return null
|
||||
@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
|
||||
|
||||
|
|
|
@ -5,7 +5,8 @@ import dorkbox.util.messagebus.utils.VarArgUtils;
|
|||
import java.util.ArrayList;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
public interface Subscriber {
|
||||
public
|
||||
interface Subscriber {
|
||||
float LOAD_FACTOR = 0.8F;
|
||||
|
||||
AtomicBoolean getVarArgPossibility();
|
||||
|
|
|
@ -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
|
||||
* 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.
|
||||
* <p>
|
||||
* <p/>
|
||||
* There will be as many unique subscription objects per message listener class as there are message handlers
|
||||
* defined in the message listeners class hierarchy.
|
||||
* <p>
|
||||
* <p/>
|
||||
* The subscription provides functionality for message publication by means of delegation to the respective
|
||||
* message dispatcher.
|
||||
*
|
||||
|
@ -26,7 +26,8 @@ import java.util.concurrent.atomic.AtomicInteger;
|
|||
* @author dorkbox, llc
|
||||
* Date: 2/2/15
|
||||
*/
|
||||
public final class Subscription {
|
||||
public final
|
||||
class Subscription {
|
||||
private static final AtomicInteger ID_COUNTER = new AtomicInteger();
|
||||
public final int ID = ID_COUNTER.getAndIncrement();
|
||||
|
||||
|
@ -37,7 +38,8 @@ public final class Subscription {
|
|||
private final IHandlerInvocation invocation;
|
||||
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.listeners = new StrongConcurrentSetV8<Object>(16, loadFactor, stripeSize);
|
||||
// this.listeners = new StrongConcurrentSet<Object>(16, 0.85F);
|
||||
|
@ -52,31 +54,37 @@ public final class Subscription {
|
|||
this.invocation = invocation;
|
||||
}
|
||||
|
||||
public MessageHandler getHandler() {
|
||||
public
|
||||
MessageHandler getHandler() {
|
||||
return handlerMetadata;
|
||||
}
|
||||
|
||||
public boolean isEmpty() {
|
||||
public
|
||||
boolean isEmpty() {
|
||||
return this.listeners.isEmpty();
|
||||
}
|
||||
|
||||
public void subscribe(Object listener) {
|
||||
public
|
||||
void subscribe(Object listener) {
|
||||
this.listeners.add(listener);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return TRUE if the element was removed
|
||||
*/
|
||||
public boolean unsubscribe(Object existingListener) {
|
||||
public
|
||||
boolean unsubscribe(Object existingListener) {
|
||||
return this.listeners.remove(existingListener);
|
||||
}
|
||||
|
||||
// only used in unit-test
|
||||
public int size() {
|
||||
public
|
||||
int 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 int handleIndex = this.handlerMetadata.getMethodIndex();
|
||||
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 int handleIndex = this.handlerMetadata.getMethodIndex();
|
||||
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 int handleIndex = this.handlerMetadata.getMethodIndex();
|
||||
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 int handleIndex = this.handlerMetadata.getMethodIndex();
|
||||
final IHandlerInvocation invocation = this.invocation;
|
||||
|
@ -138,12 +149,14 @@ public final class Subscription {
|
|||
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
public
|
||||
int hashCode() {
|
||||
return this.ID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
public
|
||||
boolean equals(Object obj) {
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -15,7 +15,8 @@ import java.util.Map;
|
|||
* @author dorkbox, llc
|
||||
* Date: 2/2/15
|
||||
*/
|
||||
public final class SubscriptionManager {
|
||||
public final
|
||||
class SubscriptionManager {
|
||||
// remember already processed classes that do not contain any message handlers
|
||||
private final Map<Class<?>, Boolean> nonListeners;
|
||||
|
||||
|
@ -31,27 +32,30 @@ public final class SubscriptionManager {
|
|||
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.subscriber = subscriber;
|
||||
this.lock = lock;
|
||||
|
||||
|
||||
// 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
|
||||
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();
|
||||
|
||||
subscriber.shutdown();
|
||||
this.subscriptionsPerListener.clear();
|
||||
}
|
||||
|
||||
public void subscribe(final Object listener) {
|
||||
public
|
||||
void subscribe(final Object listener) {
|
||||
if (listener == null) {
|
||||
return;
|
||||
}
|
||||
|
@ -133,7 +137,8 @@ public final class SubscriptionManager {
|
|||
}
|
||||
}
|
||||
|
||||
public void unsubscribe(final Object listener) {
|
||||
public
|
||||
void unsubscribe(final Object listener) {
|
||||
if (listener == null) {
|
||||
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 long stamp = lock.readLock();
|
||||
|
|
|
@ -7,25 +7,28 @@ import java.util.ArrayList;
|
|||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
|
||||
public final class ClassUtils {
|
||||
public final
|
||||
class ClassUtils {
|
||||
|
||||
private final Map<Class<?>, Class<?>> arrayCache;
|
||||
private final Map<Class<?>, Class<?>[]> superClassesCache;
|
||||
|
||||
public ClassUtils(final float loadFactor) {
|
||||
this.arrayCache = JavaVersionAdapter.get.concurrentMap(32, loadFactor, 1);
|
||||
this.superClassesCache = JavaVersionAdapter.get.concurrentMap(32, loadFactor, 1);
|
||||
public
|
||||
ClassUtils(final float loadFactor) {
|
||||
this.arrayCache = JavaVersionAdapter.concurrentMap(32, loadFactor, 1);
|
||||
this.superClassesCache = JavaVersionAdapter.concurrentMap(32, loadFactor, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* never returns null
|
||||
* 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
|
||||
* <p>
|
||||
* <p/>
|
||||
* 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.
|
||||
final Map<Class<?>, Class<?>[]> local = this.superClassesCache;
|
||||
|
||||
|
@ -75,7 +78,8 @@ public final class ClassUtils {
|
|||
* never returns null
|
||||
* never reset
|
||||
*/
|
||||
public Class<?> getArrayClass(final Class<?> c) {
|
||||
public
|
||||
Class<?> getArrayClass(final Class<?> c) {
|
||||
final Map<Class<?>, Class<?>> arrayCache = this.arrayCache;
|
||||
Class<?> clazz = arrayCache.get(c);
|
||||
|
||||
|
@ -93,12 +97,14 @@ public final class ClassUtils {
|
|||
/**
|
||||
* Clears the caches
|
||||
*/
|
||||
public void clear() {
|
||||
public
|
||||
void clear() {
|
||||
this.arrayCache.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[] arrayToSearch;
|
||||
|
@ -141,7 +147,8 @@ public final class ClassUtils {
|
|||
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> arrayToSearch;
|
||||
|
|
|
@ -16,12 +16,15 @@ import java.util.HashSet;
|
|||
* @author dorkbox
|
||||
* 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>();
|
||||
|
||||
getMethods(target, methods);
|
||||
|
@ -30,7 +33,8 @@ public final class ReflectionUtils {
|
|||
return array;
|
||||
}
|
||||
|
||||
private static void getMethods(Class<?> target, ArrayList<Method> methods) {
|
||||
private static
|
||||
void getMethods(Class<?> target, ArrayList<Method> methods) {
|
||||
try {
|
||||
for (Method method : target.getDeclaredMethods()) {
|
||||
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
|
||||
* 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;
|
||||
while (!current.equals(overridingMethod.getDeclaringClass())) {
|
||||
try {
|
||||
|
@ -70,7 +75,8 @@ public final class ReflectionUtils {
|
|||
* @param from The root class to start with
|
||||
* @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<?>>();
|
||||
|
||||
collectInterfaces(from, superclasses);
|
||||
|
@ -86,14 +92,16 @@ public final class ReflectionUtils {
|
|||
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()) {
|
||||
accumulator.add(intface);
|
||||
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;
|
||||
Method method;
|
||||
|
||||
|
@ -117,8 +125,8 @@ public final class ReflectionUtils {
|
|||
* @param <A> Class of annotation type
|
||||
* @return Annotation instance or null
|
||||
*/
|
||||
private static <A extends Annotation> A getAnnotation(AnnotatedElement from, Class<A> annotationType,
|
||||
Collection<AnnotatedElement> visited) {
|
||||
private static
|
||||
<A extends Annotation> A getAnnotation(AnnotatedElement from, Class<A> annotationType, Collection<AnnotatedElement> visited) {
|
||||
if (visited.contains(from)) {
|
||||
return null;
|
||||
}
|
||||
|
@ -136,13 +144,15 @@ public final class ReflectionUtils {
|
|||
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));
|
||||
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
|
||||
// hierarchy of the given superclass method or the method names are not the same then
|
||||
// subclassMethod does not override superclassMethod
|
||||
|
|
|
@ -8,7 +8,8 @@ import dorkbox.util.messagebus.subscription.Subscription;
|
|||
import java.util.ArrayList;
|
||||
import java.util.Map;
|
||||
|
||||
public final class SubscriptionUtils {
|
||||
public final
|
||||
class SubscriptionUtils {
|
||||
private final ClassUtils superClass;
|
||||
|
||||
// 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;
|
||||
|
||||
|
||||
public SubscriptionUtils(final ClassUtils superClass, final float loadFactor) {
|
||||
public
|
||||
SubscriptionUtils(final ClassUtils superClass, final float loadFactor) {
|
||||
this.superClass = superClass;
|
||||
|
||||
|
||||
// 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
|
||||
this.superClassSubscriptions = JavaVersionAdapter.get.concurrentMap(8, loadFactor, 1);
|
||||
this.superClassSubscriptions = JavaVersionAdapter.concurrentMap(8, loadFactor, 1);
|
||||
this.superClassSubscriptionsMulti = new HashMapTree<Class<?>, ArrayList<Subscription>>(4, loadFactor);
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
public
|
||||
void clear() {
|
||||
this.superClassSubscriptions.clear();
|
||||
this.superClassSubscriptionsMulti.clear();
|
||||
}
|
||||
|
@ -43,7 +46,8 @@ public final class SubscriptionUtils {
|
|||
*
|
||||
* @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.
|
||||
final Map<Class<?>, ArrayList<Subscription>> local = this.superClassSubscriptions;
|
||||
|
||||
|
@ -95,7 +99,8 @@ public final class SubscriptionUtils {
|
|||
*
|
||||
* @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.
|
||||
final HashMapTree<Class<?>, ArrayList<Subscription>> cached = this.superClassSubscriptionsMulti;
|
||||
|
||||
|
@ -162,8 +167,9 @@ public final class SubscriptionUtils {
|
|||
*
|
||||
* @return CAN NOT RETURN NULL
|
||||
*/
|
||||
public ArrayList<Subscription> getSuperSubscriptions(final Class<?> clazz1, final Class<?> clazz2, final Class<?> clazz3,
|
||||
final Subscriber subscriber) {
|
||||
public
|
||||
ArrayList<Subscription> getSuperSubscriptions(final Class<?> clazz1, final Class<?> clazz2, final Class<?> clazz3,
|
||||
final Subscriber subscriber) {
|
||||
// whenever our subscriptions change, this map is cleared.
|
||||
final HashMapTree<Class<?>, ArrayList<Subscription>> local = this.superClassSubscriptionsMulti;
|
||||
|
||||
|
|
|
@ -9,7 +9,8 @@ import dorkbox.util.messagebus.subscription.Subscription;
|
|||
import java.util.ArrayList;
|
||||
import java.util.Map;
|
||||
|
||||
public final class VarArgUtils {
|
||||
public final
|
||||
class VarArgUtils {
|
||||
private final Map<Class<?>, ArrayList<Subscription>> varArgSubscriptionsSingle;
|
||||
private final HashMapTree<Class<?>, ArrayList<Subscription>> varArgSubscriptionsMulti;
|
||||
|
||||
|
@ -19,19 +20,21 @@ public final class VarArgUtils {
|
|||
private final ClassUtils superClassUtils;
|
||||
|
||||
|
||||
public VarArgUtils(final ClassUtils superClassUtils, final float loadFactor) {
|
||||
public
|
||||
VarArgUtils(final ClassUtils superClassUtils, final float loadFactor) {
|
||||
|
||||
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.varArgSuperSubscriptionsSingle = JavaVersionAdapter.get.concurrentMap(16, loadFactor, 1);
|
||||
this.varArgSuperSubscriptionsSingle = JavaVersionAdapter.concurrentMap(16, loadFactor, 1);
|
||||
this.varArgSuperSubscriptionsMulti = new HashMapTree<Class<?>, ArrayList<Subscription>>(4, loadFactor);
|
||||
}
|
||||
|
||||
|
||||
public void clear() {
|
||||
public
|
||||
void clear() {
|
||||
this.varArgSubscriptionsSingle.clear();
|
||||
this.varArgSubscriptionsMulti.clear();
|
||||
|
||||
|
@ -43,7 +46,8 @@ public final class VarArgUtils {
|
|||
// CAN NOT RETURN NULL
|
||||
// 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
|
||||
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.
|
||||
final Map<Class<?>, ArrayList<Subscription>> local = this.varArgSubscriptionsSingle;
|
||||
|
||||
|
@ -84,7 +88,8 @@ public final class VarArgUtils {
|
|||
// CAN NOT RETURN NULL
|
||||
// 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
|
||||
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 Subscription[] returnedSubscriptions = new Subscription[subs.size()];
|
||||
|
@ -93,7 +98,8 @@ public final class VarArgUtils {
|
|||
}
|
||||
|
||||
// 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.
|
||||
final Map<Class<?>, ArrayList<Subscription>> local = this.varArgSuperSubscriptionsSingle;
|
||||
|
||||
|
@ -151,7 +157,8 @@ public final class VarArgUtils {
|
|||
// CAN NOT RETURN NULL
|
||||
// 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
|
||||
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.
|
||||
final HashMapTree<Class<?>, ArrayList<Subscription>> local = this.varArgSuperSubscriptionsMulti;
|
||||
|
||||
|
@ -178,8 +185,9 @@ public final class VarArgUtils {
|
|||
// CAN NOT RETURN NULL
|
||||
// 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
|
||||
public Subscription[] getVarArgSuperSubscriptions(final Class<?> messageClass1, final Class<?> messageClass2,
|
||||
final Class<?> messageClass3, final Subscriber subscriber) {
|
||||
public
|
||||
Subscription[] getVarArgSuperSubscriptions(final Class<?> messageClass1, final Class<?> messageClass2, final Class<?> messageClass3,
|
||||
final Subscriber subscriber) {
|
||||
// whenever our subscriptions change, this map is cleared.
|
||||
final HashMapTree<Class<?>, ArrayList<Subscription>> local = this.varArgSuperSubscriptionsMulti;
|
||||
|
||||
|
|
|
@ -15,7 +15,8 @@ import java.util.concurrent.ConcurrentLinkedQueue;
|
|||
import java.util.concurrent.LinkedTransferQueue;
|
||||
|
||||
|
||||
public class PerfTest_Collections {
|
||||
public
|
||||
class PerfTest_Collections {
|
||||
public static final int REPETITIONS = 10 * 1000 * 100;
|
||||
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);
|
||||
|
||||
public static void main(final String[] args) throws Exception {
|
||||
public static
|
||||
void main(final String[] args) throws Exception {
|
||||
final int size = 16;
|
||||
|
||||
|
||||
|
@ -33,52 +35,56 @@ public class PerfTest_Collections {
|
|||
// have to warm-up the JVM.
|
||||
System.err.print("\nWarming up JVM.");
|
||||
// for (int i=0;i<2;i++) {
|
||||
bench(size, new ConcurrentLinkedQueue<Subscription>(), false);
|
||||
System.err.print(".");
|
||||
bench(size, new ArrayList<Subscription>(size*2), false);
|
||||
System.err.print(".");
|
||||
bench(size, new ArrayDeque<Subscription>(size*2), false);
|
||||
System.err.print(".");
|
||||
bench(size, new ConcurrentLinkedQueue<Subscription>(), false);
|
||||
System.err.print(".");
|
||||
bench(size, new LinkedList<Subscription>(), false);
|
||||
System.err.print(".");
|
||||
bench(size, new ConcurrentLinkedQueue<Subscription>(), false);
|
||||
System.err.print(".");
|
||||
bench(size, new ArrayList<Subscription>(size * 2), false);
|
||||
System.err.print(".");
|
||||
bench(size, new ArrayDeque<Subscription>(size * 2), false);
|
||||
System.err.print(".");
|
||||
bench(size, new ConcurrentLinkedQueue<Subscription>(), false);
|
||||
System.err.print(".");
|
||||
bench(size, new LinkedList<Subscription>(), false);
|
||||
System.err.print(".");
|
||||
// }
|
||||
System.err.println("Done");
|
||||
|
||||
bench(size, new ArrayList<Subscription>(size*2));
|
||||
bench(size, new ConcurrentSet<Subscription>(size*2, LOAD_FACTOR, 5));
|
||||
bench(size, new ArrayList<Subscription>(size * 2));
|
||||
bench(size, new ConcurrentSet<Subscription>(size * 2, LOAD_FACTOR, 5));
|
||||
bench(size, new ConcurrentLinkedQueue2<Subscription>());
|
||||
bench(size, new ConcurrentLinkedQueue<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 StrongConcurrentSetV8<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, new StrongConcurrentSetV8<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, new HashSet<Subscription>());
|
||||
// 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);
|
||||
}
|
||||
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 runs = 3;
|
||||
|
||||
for (int i=0;i<size;i++) {
|
||||
for (int i = 0; i < size; i++) {
|
||||
for (MessageHandler x : allHandlers) {
|
||||
set.add(new Subscription(x, .85F, 1));
|
||||
}
|
||||
}
|
||||
|
||||
if (!showOutput) {
|
||||
for (int i=2;i<6;i++) {
|
||||
for (int i = 2; i < 6; i++) {
|
||||
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);
|
||||
System.out.format("summary,IteratorPerfTest,%s - %,d (%d)\n", set.getClass().getSimpleName(), average, i);
|
||||
}
|
||||
|
@ -87,11 +93,13 @@ public class PerfTest_Collections {
|
|||
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;
|
||||
final long[] results = new long[runs];
|
||||
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) {
|
||||
System.gc();
|
||||
Thread.sleep(100L);
|
||||
|
@ -104,24 +112,25 @@ public class PerfTest_Collections {
|
|||
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];
|
||||
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);
|
||||
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();
|
||||
}
|
||||
|
||||
for (int i=0;i<concurrency;i++) {
|
||||
for (int i = 0; i < concurrency; i++) {
|
||||
threads[i].join();
|
||||
}
|
||||
|
||||
|
@ -129,7 +138,7 @@ public class PerfTest_Collections {
|
|||
long end = -1;
|
||||
long count = 0;
|
||||
|
||||
for (int i=0;i<concurrency;i++) {
|
||||
for (int i = 0; i < concurrency; i++) {
|
||||
if (producers[i].start < start) {
|
||||
start = producers[i].start;
|
||||
}
|
||||
|
@ -143,7 +152,7 @@ public class PerfTest_Collections {
|
|||
|
||||
|
||||
long duration = end - start;
|
||||
long ops = repetitions * 1_000_000_000L / duration;
|
||||
long ops = repetitions * 1000000000L / duration;
|
||||
|
||||
if (showStats) {
|
||||
System.out.format("%d (%d) - ops/sec=%,d\n", runNumber, count, ops);
|
||||
|
@ -151,21 +160,24 @@ public class PerfTest_Collections {
|
|||
return ops;
|
||||
}
|
||||
|
||||
public static class Producer implements Runnable {
|
||||
public static
|
||||
class Producer implements Runnable {
|
||||
private final Collection<Subscription> set;
|
||||
volatile long start;
|
||||
volatile long end;
|
||||
private int repetitions;
|
||||
volatile int count;
|
||||
|
||||
public Producer(Collection<Subscription> set, int repetitions) {
|
||||
public
|
||||
Producer(Collection<Subscription> set, int repetitions) {
|
||||
this.set = set;
|
||||
this.repetitions = repetitions;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@Override
|
||||
public void run() {
|
||||
public
|
||||
void run() {
|
||||
Collection<Subscription> set = this.set;
|
||||
int i = this.repetitions;
|
||||
this.start = System.nanoTime();
|
||||
|
@ -178,7 +190,7 @@ public class PerfTest_Collections {
|
|||
int count = 0;
|
||||
|
||||
do {
|
||||
for (iterator = set.iterator(); iterator.hasNext();) {
|
||||
for (iterator = set.iterator(); iterator.hasNext(); ) {
|
||||
sub = iterator.next();
|
||||
// if (sub.acceptsSubtypes()) {
|
||||
// count--;
|
||||
|
@ -201,14 +213,18 @@ public class PerfTest_Collections {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public static class Listener {
|
||||
public static
|
||||
class Listener {
|
||||
@Handler
|
||||
public void handleSync(Integer o1) {
|
||||
public
|
||||
void handleSync(Integer o1) {
|
||||
}
|
||||
|
||||
@Handler(acceptVarargs=true)
|
||||
public void handleSync(Object... o) {
|
||||
@Handler(acceptVarargs = true)
|
||||
public
|
||||
void handleSync(Object... o) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,13 +3,15 @@ package dorkbox.util.messagebus;
|
|||
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 Integer TEST_VALUE = Integer.valueOf(777);
|
||||
|
||||
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);
|
||||
|
||||
final int warmupRuns = 4;
|
||||
|
@ -24,8 +26,8 @@ public class PerfTest_MBassador {
|
|||
System.out.format("summary,PublishPerfTest, %,d\n", average);
|
||||
}
|
||||
|
||||
public static long averageRun(int warmUpRuns, int sumCount, MessageBus bus, boolean showStats, int concurrency, int repetitions)
|
||||
throws Exception {
|
||||
public static
|
||||
long averageRun(int warmUpRuns, int sumCount, MessageBus bus, boolean showStats, int concurrency, int repetitions) throws Exception {
|
||||
int runs = warmUpRuns + sumCount;
|
||||
final long[] results = new long[runs];
|
||||
for (int i = 0; i < runs; i++) {
|
||||
|
@ -38,32 +40,32 @@ public class PerfTest_MBassador {
|
|||
sum += results[i];
|
||||
}
|
||||
|
||||
return sum/sumCount;
|
||||
return sum / sumCount;
|
||||
}
|
||||
|
||||
private static long performanceRun(int runNumber, MessageBus bus, boolean showStats, int concurrency, int repetitions)
|
||||
throws Exception {
|
||||
private static
|
||||
long performanceRun(int runNumber, MessageBus bus, boolean showStats, int concurrency, int repetitions) throws Exception {
|
||||
|
||||
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);
|
||||
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();
|
||||
}
|
||||
|
||||
for (int i=0;i<concurrency;i++) {
|
||||
for (int i = 0; i < concurrency; i++) {
|
||||
threads[i].join();
|
||||
}
|
||||
|
||||
long start = Long.MAX_VALUE;
|
||||
long end = -1;
|
||||
|
||||
for (int i=0;i<concurrency;i++) {
|
||||
for (int i = 0; i < concurrency; i++) {
|
||||
if (producers[i].start < start) {
|
||||
start = producers[i].start;
|
||||
}
|
||||
|
@ -75,7 +77,7 @@ public class PerfTest_MBassador {
|
|||
|
||||
|
||||
long duration = end - start;
|
||||
long ops = repetitions * 1_000_000_000L / duration;
|
||||
long ops = repetitions * 1000000000L / duration;
|
||||
|
||||
if (showStats) {
|
||||
System.out.format("%d - ops/sec=%,d\n", runNumber, ops);
|
||||
|
@ -83,19 +85,22 @@ public class PerfTest_MBassador {
|
|||
return ops;
|
||||
}
|
||||
|
||||
public static class Producer implements Runnable {
|
||||
public static
|
||||
class Producer implements Runnable {
|
||||
private final MessageBus bus;
|
||||
volatile long start;
|
||||
volatile long end;
|
||||
private int repetitions;
|
||||
|
||||
public Producer(MessageBus bus, int repetitions) {
|
||||
public
|
||||
Producer(MessageBus bus, int repetitions) {
|
||||
this.bus = bus;
|
||||
this.repetitions = repetitions;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
public
|
||||
void run() {
|
||||
MessageBus bus = this.bus;
|
||||
int i = this.repetitions;
|
||||
this.start = System.nanoTime();
|
||||
|
@ -108,14 +113,18 @@ public class PerfTest_MBassador {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public static class Listener {
|
||||
public static
|
||||
class Listener {
|
||||
@Handler
|
||||
public void handleSync(Integer o1) {
|
||||
public
|
||||
void handleSync(Integer o1) {
|
||||
}
|
||||
|
||||
@Handler(acceptVarargs=true)
|
||||
public void handleSync(Object... o) {
|
||||
@Handler(acceptVarargs = true)
|
||||
public
|
||||
void handleSync(Object... o) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue