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