WIP - getting system to arrays instead of lists
This commit is contained in:
parent
0401a6a164
commit
9e06d16855
|
@ -27,7 +27,6 @@ import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.concurrent.ConcurrentMap;
|
import java.util.concurrent.ConcurrentMap;
|
||||||
import java.util.concurrent.CopyOnWriteArrayList;
|
|
||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
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
|
||||||
|
@ -67,7 +66,7 @@ class SubscriptionManager {
|
||||||
// all subscriptions per message type. We perpetually KEEP the types, as this lowers the amount of locking required
|
// all subscriptions per message type. We perpetually KEEP the types, as this lowers the amount of locking required
|
||||||
// this is the primary list for dispatching a specific message
|
// this is the primary list for dispatching a specific message
|
||||||
// write access is synchronized and happens only when a listener of a specific class is registered the first time
|
// write access is synchronized and happens only when a listener of a specific class is registered the first time
|
||||||
final ConcurrentMap<Class<?>, List<Subscription>> subscriptionsPerMessageSingle;
|
final ConcurrentMap<Class<?>, Subscription[]> subscriptionsPerMessageSingle;
|
||||||
private final HashMapTree<Class<?>, ArrayList<Subscription>> subscriptionsPerMessageMulti;
|
private final HashMapTree<Class<?>, ArrayList<Subscription>> subscriptionsPerMessageMulti;
|
||||||
|
|
||||||
// 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)
|
||||||
|
@ -89,7 +88,7 @@ class SubscriptionManager {
|
||||||
this.nonListeners = new ConcurrentHashMap<Class<?>, Boolean>(4, LOAD_FACTOR, numberOfThreads);
|
this.nonListeners = new ConcurrentHashMap<Class<?>, Boolean>(4, LOAD_FACTOR, numberOfThreads);
|
||||||
|
|
||||||
subscriptionsPerListener = new ConcurrentHashMap<Class<?>, Subscription[]>(32, LOAD_FACTOR, numberOfThreads);
|
subscriptionsPerListener = new ConcurrentHashMap<Class<?>, Subscription[]>(32, LOAD_FACTOR, numberOfThreads);
|
||||||
subscriptionsPerMessageSingle = new ConcurrentHashMap<Class<?>, List<Subscription>>(32, LOAD_FACTOR, numberOfThreads);
|
subscriptionsPerMessageSingle = new ConcurrentHashMap<Class<?>, Subscription[]>(32, LOAD_FACTOR, numberOfThreads);
|
||||||
|
|
||||||
this.subscriptionsPerMessageMulti = new HashMapTree<Class<?>, ArrayList<Subscription>>();
|
this.subscriptionsPerMessageMulti = new HashMapTree<Class<?>, ArrayList<Subscription>>();
|
||||||
|
|
||||||
|
@ -180,7 +179,7 @@ class SubscriptionManager {
|
||||||
Class<?> handlerType;
|
Class<?> handlerType;
|
||||||
|
|
||||||
// create the subscriptions
|
// create the subscriptions
|
||||||
final ConcurrentMap<Class<?>, List<Subscription>> subsPerMessageSingle = this.subscriptionsPerMessageSingle;
|
final ConcurrentMap<Class<?>, Subscription[]> subsPerMessageSingle = this.subscriptionsPerMessageSingle;
|
||||||
subscriptions = new Subscription[handlersSize];
|
subscriptions = new Subscription[handlersSize];
|
||||||
|
|
||||||
for (int i = 0; i < handlersSize; i++) {
|
for (int i = 0; i < handlersSize; i++) {
|
||||||
|
@ -198,7 +197,7 @@ class SubscriptionManager {
|
||||||
handlerType = messageHandlerTypes[0];
|
handlerType = messageHandlerTypes[0];
|
||||||
|
|
||||||
if (!subsPerMessageSingle.containsKey(handlerType)) {
|
if (!subsPerMessageSingle.containsKey(handlerType)) {
|
||||||
subsPerMessageSingle.put(handlerType, new CopyOnWriteArrayList<Subscription>());
|
subsPerMessageSingle.put(handlerType, new Subscription[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -220,6 +219,9 @@ class SubscriptionManager {
|
||||||
} else {
|
} else {
|
||||||
// we can now safely add for publication AND subscribe since the data structures are consistent
|
// we can now safely add for publication AND subscribe since the data structures are consistent
|
||||||
for (int i = 0; i < handlersSize; i++) {
|
for (int i = 0; i < handlersSize; i++) {
|
||||||
|
// register the super types/varity types
|
||||||
|
subUtils.register(listenerClass, this);
|
||||||
|
|
||||||
subscription = subscriptions[i];
|
subscription = subscriptions[i];
|
||||||
subscription.subscribe(listener); // register this callback listener to this subscription
|
subscription.subscribe(listener); // register this callback listener to this subscription
|
||||||
|
|
||||||
|
@ -231,7 +233,14 @@ class SubscriptionManager {
|
||||||
handlerType = messageHandlerTypes[0];
|
handlerType = messageHandlerTypes[0];
|
||||||
|
|
||||||
// makes this subscription visible for publication
|
// makes this subscription visible for publication
|
||||||
subsPerMessageSingle.get(handlerType).add(subscription);
|
final Subscription[] currentSubs = subsPerMessageSingle.get(handlerType);
|
||||||
|
final int currentLength = currentSubs.length;
|
||||||
|
|
||||||
|
// add the new subscription to the beginning of the array
|
||||||
|
final Subscription[] newSubs = new Subscription[currentLength + 1];
|
||||||
|
newSubs[0] = subscription;
|
||||||
|
System.arraycopy(currentSubs, 0, newSubs, 1, currentLength);
|
||||||
|
subsPerMessageSingle.put(handlerType, newSubs);
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
@ -362,7 +371,7 @@ class SubscriptionManager {
|
||||||
|
|
||||||
|
|
||||||
public
|
public
|
||||||
List<Subscription> getExactAsArray(final Class<?> messageClass) {
|
Subscription[] getExactAsArray(final Class<?> messageClass) {
|
||||||
return subscriptionsPerMessageSingle.get(messageClass);
|
return subscriptionsPerMessageSingle.get(messageClass);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -379,17 +388,7 @@ class SubscriptionManager {
|
||||||
// can return null
|
// can return null
|
||||||
public
|
public
|
||||||
Subscription[] getExact(final Class<?> messageClass) {
|
Subscription[] getExact(final Class<?> messageClass) {
|
||||||
final List<Subscription> collection = getExactAsArray(messageClass);
|
return getExactAsArray(messageClass);
|
||||||
|
|
||||||
if (collection != null) {
|
|
||||||
// convert to Array because the subscriptions can change and we want safe iteration over the list
|
|
||||||
final Subscription[] subscriptions = new Subscription[collection.size()];
|
|
||||||
collection.toArray(subscriptions);
|
|
||||||
|
|
||||||
return subscriptions;
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// can return null
|
// can return null
|
||||||
|
@ -423,32 +422,26 @@ class SubscriptionManager {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// can return null
|
// can NOT return null
|
||||||
public
|
public
|
||||||
Subscription[] getExactAndSuper(final Class<?> messageClass) {
|
Subscription[] getExactAndSuper(final Class<?> messageClass) {
|
||||||
List<Subscription> collection = getExactAsArray(messageClass); // can return null
|
Subscription[] collection = getExactAsArray(messageClass); // can return null
|
||||||
|
|
||||||
// now publish superClasses
|
// now publish superClasses
|
||||||
final ArrayList<Subscription> superSubscriptions = this.subUtils.getSuperSubscriptions(messageClass, this); // NOT return null
|
final Subscription[] superSubscriptions = this.subUtils.getSuperSubscriptions(messageClass, this); // NOT return null
|
||||||
|
|
||||||
if (collection != null) {
|
if (collection != null) {
|
||||||
collection = new ArrayList<Subscription>(collection);
|
final int length = collection.length;
|
||||||
|
final int lengthSuper = superSubscriptions.length;
|
||||||
|
|
||||||
if (!superSubscriptions.isEmpty()) {
|
final Subscription[] newSubs = new Subscription[length + lengthSuper];
|
||||||
collection.addAll(superSubscriptions);
|
System.arraycopy(collection, 0, newSubs, 0, length);
|
||||||
}
|
System.arraycopy(superSubscriptions, 0, newSubs, length, lengthSuper);
|
||||||
}
|
|
||||||
else if (!superSubscriptions.isEmpty()) {
|
|
||||||
collection = superSubscriptions;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (collection != null) {
|
return newSubs;
|
||||||
final Subscription[] subscriptions = new Subscription[collection.size()];
|
|
||||||
collection.toArray(subscriptions);
|
|
||||||
return subscriptions;
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return null;
|
return superSubscriptions;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -95,15 +95,18 @@ class ClassUtils {
|
||||||
* race conditions will result in duplicate answers, which we don't care if happens
|
* race conditions will result in duplicate answers, which we don't care if happens
|
||||||
* never returns null
|
* never returns null
|
||||||
* never resets
|
* never resets
|
||||||
|
*
|
||||||
|
* https://bugs.openjdk.java.net/browse/JDK-6525802 (fixed this in 2007, so Array.newInstance is just as fast (via intrinsics) new [])
|
||||||
*/
|
*/
|
||||||
public
|
public
|
||||||
Class<?> getArrayClass(final Class<?> c) {
|
Class<?> getArrayClass(final Class<?> c) {
|
||||||
|
// this is never reset, since it never needs to be.
|
||||||
final Map<Class<?>, Class<?>> cache = this.arrayCache;
|
final Map<Class<?>, Class<?>> cache = this.arrayCache;
|
||||||
Class<?> clazz = cache.get(c);
|
Class<?> clazz = cache.get(c);
|
||||||
|
|
||||||
if (clazz == null) {
|
if (clazz == null) {
|
||||||
// messy, but the ONLY way to do it. Array super types are also arrays
|
// messy, but the ONLY way to do it. Array super types are also arrays
|
||||||
final Object[] newInstance = (Object[]) Array.newInstance(c, 1);
|
final Object[] newInstance = (Object[]) Array.newInstance(c, 0);
|
||||||
clazz = newInstance.getClass();
|
clazz = newInstance.getClass();
|
||||||
cache.put(c, clazz);
|
cache.put(c, clazz);
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,7 +20,6 @@ import dorkbox.util.messagebus.subscription.Subscription;
|
||||||
import dorkbox.util.messagebus.subscription.SubscriptionManager;
|
import dorkbox.util.messagebus.subscription.SubscriptionManager;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
|
@ -31,7 +30,7 @@ class SubscriptionUtils {
|
||||||
// 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 REALLY improves performance on handlers
|
// it's a hit on SUB/UNSUB, but REALLY improves performance on handlers
|
||||||
// it's faster to create a new one for SUB/UNSUB than it is to shutdown() on the original one
|
// it's faster to create a new one for SUB/UNSUB than it is to shutdown() on the original one
|
||||||
private final Map<Class<?>, ArrayList<Subscription>> superClassSubscriptions;
|
private final Map<Class<?>, Subscription[]> superClassSubscriptions;
|
||||||
private final HashMapTree<Class<?>, ArrayList<Subscription>> superClassSubscriptionsMulti;
|
private final HashMapTree<Class<?>, ArrayList<Subscription>> superClassSubscriptionsMulti;
|
||||||
|
|
||||||
|
|
||||||
|
@ -42,7 +41,7 @@ class SubscriptionUtils {
|
||||||
|
|
||||||
// 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 = new ConcurrentHashMap<Class<?>, ArrayList<Subscription>>(8, loadFactor, numberOfThreads);
|
this.superClassSubscriptions = new ConcurrentHashMap<Class<?>, Subscription[]>(8, loadFactor, numberOfThreads);
|
||||||
this.superClassSubscriptionsMulti = new HashMapTree<Class<?>, ArrayList<Subscription>>();
|
this.superClassSubscriptionsMulti = new HashMapTree<Class<?>, ArrayList<Subscription>>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -52,6 +51,46 @@ class SubscriptionUtils {
|
||||||
this.superClassSubscriptionsMulti.clear();
|
this.superClassSubscriptionsMulti.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ALWAYS register and create a cached version of the requested class + superClasses
|
||||||
|
public
|
||||||
|
Subscription[] register(final Class<?> clazz, final SubscriptionManager subManager) {
|
||||||
|
final Map<Class<?>, Subscription[]> local = this.superClassSubscriptions;
|
||||||
|
|
||||||
|
// types was not empty, so collect subscriptions for each type and collate them
|
||||||
|
|
||||||
|
// save the subscriptions
|
||||||
|
final Class<?>[] superClasses = this.superClass.getSuperClasses(clazz); // never returns null, cached response
|
||||||
|
|
||||||
|
Class<?> superClass;
|
||||||
|
Subscription[] superSubs;
|
||||||
|
Subscription sub;
|
||||||
|
|
||||||
|
final int length = superClasses.length;
|
||||||
|
int superSubLength;
|
||||||
|
final ArrayList<Subscription> subsAsList = new ArrayList<Subscription>(length);
|
||||||
|
|
||||||
|
for (int i = 0; i < length; i++) {
|
||||||
|
superClass = superClasses[i];
|
||||||
|
superSubs = subManager.getExactAsArray(superClass);
|
||||||
|
|
||||||
|
if (superSubs != null) {
|
||||||
|
superSubLength = superSubs.length;
|
||||||
|
for (int j = 0; j < superSubLength; j++) {
|
||||||
|
sub = superSubs[j];
|
||||||
|
|
||||||
|
if (sub.getHandler().acceptsSubtypes()) {
|
||||||
|
subsAsList.add(sub);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Subscription[] subs = new Subscription[subsAsList.size()];
|
||||||
|
subsAsList.toArray(subs);
|
||||||
|
local.put(clazz, subs);
|
||||||
|
|
||||||
|
return subs;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns an array COPY of the super subscriptions for the specified type.
|
* Returns an array COPY of the super subscriptions for the specified type.
|
||||||
|
@ -61,47 +100,16 @@ class SubscriptionUtils {
|
||||||
* @return CAN NOT RETURN NULL
|
* @return CAN NOT RETURN NULL
|
||||||
*/
|
*/
|
||||||
public
|
public
|
||||||
ArrayList<Subscription> getSuperSubscriptions(final Class<?> clazz, final SubscriptionManager subManager) {
|
Subscription[] getSuperSubscriptions(final Class<?> clazz, final SubscriptionManager subManager) {
|
||||||
// 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<?>, Subscription[]> local = this.superClassSubscriptions;
|
||||||
|
Subscription[] subs = local.get(clazz);
|
||||||
|
|
||||||
ArrayList<Subscription> subs = local.get(clazz);
|
if (subs != null) {
|
||||||
|
return subs;
|
||||||
if (subs == null) {
|
|
||||||
// types was not empty, so collect subscriptions for each type and collate them
|
|
||||||
|
|
||||||
// save the subscriptions
|
|
||||||
final Class<?>[] superClasses = this.superClass.getSuperClasses(clazz); // never returns null, cached response
|
|
||||||
|
|
||||||
Class<?> superClass;
|
|
||||||
List<Subscription> superSubs;
|
|
||||||
Subscription sub;
|
|
||||||
|
|
||||||
final int length = superClasses.length;
|
|
||||||
int superSubLength;
|
|
||||||
subs = new ArrayList<Subscription>(length);
|
|
||||||
|
|
||||||
for (int i = 0; i < length; i++) {
|
|
||||||
superClass = superClasses[i];
|
|
||||||
superSubs = subManager.getExactAsArray(superClass);
|
|
||||||
|
|
||||||
if (superSubs != null) {
|
|
||||||
superSubLength = superSubs.size();
|
|
||||||
for (int j = 0; j < superSubLength; j++) {
|
|
||||||
sub = superSubs.get(j);
|
|
||||||
|
|
||||||
if (sub.getHandler().acceptsSubtypes()) {
|
|
||||||
subs.add(sub);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
subs.trimToSize();
|
|
||||||
local.put(clazz, subs);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return subs;
|
return register(clazz, subManager);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -21,16 +21,15 @@ import dorkbox.util.messagebus.subscription.Subscription;
|
||||||
import dorkbox.util.messagebus.subscription.SubscriptionManager;
|
import dorkbox.util.messagebus.subscription.SubscriptionManager;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
public final
|
public final
|
||||||
class VarArgUtils {
|
class VarArgUtils {
|
||||||
private final Map<Class<?>, ArrayList<Subscription>> varArgSubscriptionsSingle;
|
private final Map<Class<?>, Subscription[]> varArgSubscriptionsSingle;
|
||||||
private final HashMapTree<Class<?>, ArrayList<Subscription>> varArgSubscriptionsMulti;
|
private final HashMapTree<Class<?>, ArrayList<Subscription>> varArgSubscriptionsMulti;
|
||||||
|
|
||||||
private final Map<Class<?>, ArrayList<Subscription>> varArgSuperSubscriptionsSingle;
|
private final Map<Class<?>, Subscription[]> varArgSuperSubscriptionsSingle;
|
||||||
private final HashMapTree<Class<?>, ArrayList<Subscription>> varArgSuperSubscriptionsMulti;
|
private final HashMapTree<Class<?>, ArrayList<Subscription>> varArgSuperSubscriptionsMulti;
|
||||||
|
|
||||||
private final ClassUtils superClassUtils;
|
private final ClassUtils superClassUtils;
|
||||||
|
@ -41,10 +40,10 @@ class VarArgUtils {
|
||||||
|
|
||||||
this.superClassUtils = superClassUtils;
|
this.superClassUtils = superClassUtils;
|
||||||
|
|
||||||
this.varArgSubscriptionsSingle = new ConcurrentHashMap<Class<?>, ArrayList<Subscription>>(16, loadFactor, numberOfThreads);
|
this.varArgSubscriptionsSingle = new ConcurrentHashMap<Class<?>, Subscription[]>(16, loadFactor, numberOfThreads);
|
||||||
this.varArgSubscriptionsMulti = new HashMapTree<Class<?>, ArrayList<Subscription>>();
|
this.varArgSubscriptionsMulti = new HashMapTree<Class<?>, ArrayList<Subscription>>();
|
||||||
|
|
||||||
this.varArgSuperSubscriptionsSingle = new ConcurrentHashMap<Class<?>, ArrayList<Subscription>>(16, loadFactor, numberOfThreads);
|
this.varArgSuperSubscriptionsSingle = new ConcurrentHashMap<Class<?>, Subscription[]>(16, loadFactor, numberOfThreads);
|
||||||
this.varArgSuperSubscriptionsMulti = new HashMapTree<Class<?>, ArrayList<Subscription>>();
|
this.varArgSuperSubscriptionsMulti = new HashMapTree<Class<?>, ArrayList<Subscription>>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -65,38 +64,39 @@ class VarArgUtils {
|
||||||
public
|
public
|
||||||
Subscription[] getVarArgSubscriptions(final Class<?> messageClass, final SubscriptionManager subManager) {
|
Subscription[] getVarArgSubscriptions(final Class<?> messageClass, final SubscriptionManager subManager) {
|
||||||
// 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<?>, Subscription[]> local = this.varArgSubscriptionsSingle;
|
||||||
|
|
||||||
ArrayList<Subscription> varArgSubs = local.get(messageClass);
|
Subscription[] varArgSubs = local.get(messageClass);
|
||||||
|
|
||||||
if (varArgSubs == null) {
|
if (varArgSubs == null) {
|
||||||
// this gets (and caches) our array type. This is never cleared.
|
// this gets (and caches) our array type. This is never cleared.
|
||||||
final Class<?> arrayVersion = this.superClassUtils.getArrayClass(messageClass);
|
final Class<?> arrayVersion = this.superClassUtils.getArrayClass(messageClass);
|
||||||
|
|
||||||
final List<Subscription> subs = subManager.getExactAsArray(arrayVersion);
|
final Subscription[] subs = subManager.getExactAsArray(arrayVersion);
|
||||||
if (subs != null) {
|
if (subs != null) {
|
||||||
final int length = subs.size();
|
final int length = subs.length;
|
||||||
varArgSubs = new ArrayList<Subscription>(length);
|
final ArrayList<Subscription> varArgSubsAsList = new ArrayList<Subscription>(length);
|
||||||
|
|
||||||
Subscription sub;
|
Subscription sub;
|
||||||
for (int i = 0; i < length; i++) {
|
for (int i = 0; i < length; i++) {
|
||||||
sub = subs.get(i);
|
sub = subs[i];
|
||||||
|
|
||||||
if (sub.getHandler().acceptsVarArgs()) {
|
if (sub.getHandler().acceptsVarArgs()) {
|
||||||
varArgSubs.add(sub);
|
varArgSubsAsList.add(sub);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
varArgSubs = new Subscription[varArgSubsAsList.size()];
|
||||||
|
varArgSubsAsList.toArray(varArgSubs);
|
||||||
|
|
||||||
local.put(messageClass, varArgSubs);
|
local.put(messageClass, varArgSubs);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
varArgSubs = new ArrayList<Subscription>(0);
|
varArgSubs = new Subscription[0];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
final Subscription[] subscriptions = new Subscription[varArgSubs.size()];
|
return varArgSubs;
|
||||||
varArgSubs.toArray(subscriptions);
|
|
||||||
return subscriptions;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -106,20 +106,10 @@ class VarArgUtils {
|
||||||
// and then, returns the array'd version superclass subscriptions
|
// and then, returns the array'd version superclass subscriptions
|
||||||
public
|
public
|
||||||
Subscription[] getVarArgSuperSubscriptions(final Class<?> messageClass, final SubscriptionManager subManager) {
|
Subscription[] getVarArgSuperSubscriptions(final Class<?> messageClass, final SubscriptionManager subManager) {
|
||||||
final ArrayList<Subscription> subs = getVarArgSuperSubscriptions_List(messageClass, subManager);
|
|
||||||
|
|
||||||
final Subscription[] returnedSubscriptions = new Subscription[subs.size()];
|
|
||||||
subs.toArray(returnedSubscriptions);
|
|
||||||
return returnedSubscriptions;
|
|
||||||
}
|
|
||||||
|
|
||||||
// CAN NOT RETURN NULL
|
|
||||||
private
|
|
||||||
ArrayList<Subscription> getVarArgSuperSubscriptions_List(final Class<?> messageClass, final SubscriptionManager subManager) {
|
|
||||||
// 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<?>, Subscription[]> local = this.varArgSuperSubscriptionsSingle;
|
||||||
|
|
||||||
ArrayList<Subscription> varArgSuperSubs = local.get(messageClass);
|
Subscription[] varArgSuperSubs = local.get(messageClass);
|
||||||
|
|
||||||
if (varArgSuperSubs == null) {
|
if (varArgSuperSubs == null) {
|
||||||
// this gets (and caches) our array type. This is never cleared.
|
// this gets (and caches) our array type. This is never cleared.
|
||||||
|
@ -127,7 +117,7 @@ class VarArgUtils {
|
||||||
final Class<?>[] types = this.superClassUtils.getSuperClasses(arrayVersion);
|
final Class<?>[] types = this.superClassUtils.getSuperClasses(arrayVersion);
|
||||||
|
|
||||||
final int typesLength = types.length;
|
final int typesLength = types.length;
|
||||||
varArgSuperSubs = new ArrayList<Subscription>(typesLength);
|
varArgSuperSubs = new Subscription[typesLength];
|
||||||
|
|
||||||
if (typesLength == 0) {
|
if (typesLength == 0) {
|
||||||
local.put(messageClass, varArgSuperSubs);
|
local.put(messageClass, varArgSuperSubs);
|
||||||
|
@ -135,9 +125,10 @@ class VarArgUtils {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// there are varArgs super classes for this messageClass
|
||||||
Class<?> type;
|
Class<?> type;
|
||||||
Subscription sub;
|
Subscription sub;
|
||||||
List<Subscription> subs;
|
Subscription[] subs;
|
||||||
int length;
|
int length;
|
||||||
MessageHandler handlerMetadata;
|
MessageHandler handlerMetadata;
|
||||||
|
|
||||||
|
@ -146,20 +137,23 @@ class VarArgUtils {
|
||||||
subs = subManager.getExactAsArray(type);
|
subs = subManager.getExactAsArray(type);
|
||||||
|
|
||||||
if (subs != null) {
|
if (subs != null) {
|
||||||
length = subs.size();
|
length = subs.length;
|
||||||
varArgSuperSubs = new ArrayList<Subscription>(length);
|
final ArrayList<Subscription> varArgSuperSubsAsList = new ArrayList<Subscription>(length);
|
||||||
|
|
||||||
for (int j = 0; j < length; j++) {
|
for (int j = 0; j < length; j++) {
|
||||||
sub = subs.get(j);
|
sub = subs[j];
|
||||||
|
|
||||||
handlerMetadata = sub.getHandler();
|
handlerMetadata = sub.getHandler();
|
||||||
if (handlerMetadata.acceptsSubtypes() && handlerMetadata.acceptsVarArgs()) {
|
if (handlerMetadata.acceptsSubtypes() && handlerMetadata.acceptsVarArgs()) {
|
||||||
varArgSuperSubs.add(sub);
|
varArgSuperSubsAsList.add(sub);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
varArgSuperSubs = new Subscription[varArgSuperSubsAsList.size()];
|
||||||
|
varArgSuperSubsAsList.toArray(varArgSuperSubs);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
varArgSuperSubs = new ArrayList<Subscription>(0);
|
varArgSuperSubs = new Subscription[0];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -180,17 +174,17 @@ class VarArgUtils {
|
||||||
|
|
||||||
ArrayList<Subscription> subs = local.get(messageClass1, messageClass2);
|
ArrayList<Subscription> subs = local.get(messageClass1, messageClass2);
|
||||||
|
|
||||||
if (subs == null) {
|
// if (subs == null) {
|
||||||
// the message class types are not the same, so look for a common superClass varArg subscription.
|
// // the message class types are not the same, so look for a common superClass varArg subscription.
|
||||||
// this is to publish to object[] (or any class[]) handler that is common among all superTypes of the messages
|
// // this is to publish to object[] (or any class[]) handler that is common among all superTypes of the messages
|
||||||
final ArrayList<Subscription> varargSuperSubscriptions1 = getVarArgSuperSubscriptions_List(messageClass1, subManager);
|
// final ArrayList<Subscription> varargSuperSubscriptions1 = getVarArgSuperSubscriptions_List(messageClass1, subManager);
|
||||||
final ArrayList<Subscription> varargSuperSubscriptions2 = getVarArgSuperSubscriptions_List(messageClass2, subManager);
|
// final ArrayList<Subscription> varargSuperSubscriptions2 = getVarArgSuperSubscriptions_List(messageClass2, subManager);
|
||||||
|
//
|
||||||
subs = ClassUtils.findCommon(varargSuperSubscriptions1, varargSuperSubscriptions2);
|
// subs = ClassUtils.findCommon(varargSuperSubscriptions1, varargSuperSubscriptions2);
|
||||||
|
//
|
||||||
subs.trimToSize();
|
// subs.trimToSize();
|
||||||
local.put(subs, messageClass1, messageClass2);
|
// local.put(subs, messageClass1, messageClass2);
|
||||||
}
|
// }
|
||||||
|
|
||||||
final Subscription[] returnedSubscriptions = new Subscription[subs.size()];
|
final Subscription[] returnedSubscriptions = new Subscription[subs.size()];
|
||||||
subs.toArray(returnedSubscriptions);
|
subs.toArray(returnedSubscriptions);
|
||||||
|
@ -209,19 +203,19 @@ class VarArgUtils {
|
||||||
|
|
||||||
ArrayList<Subscription> subs = local.get(messageClass1, messageClass2, messageClass3);
|
ArrayList<Subscription> subs = local.get(messageClass1, messageClass2, messageClass3);
|
||||||
|
|
||||||
if (subs == null) {
|
// if (subs == null) {
|
||||||
// the message class types are not the same, so look for a common superClass varArg subscription.
|
// // the message class types are not the same, so look for a common superClass varArg subscription.
|
||||||
// this is to publish to object[] (or any class[]) handler that is common among all superTypes of the messages
|
// // this is to publish to object[] (or any class[]) handler that is common among all superTypes of the messages
|
||||||
final ArrayList<Subscription> varargSuperSubscriptions1 = getVarArgSuperSubscriptions_List(messageClass1, subManager);
|
// final ArrayList<Subscription> varargSuperSubscriptions1 = getVarArgSuperSubscriptions_List(messageClass1, subManager);
|
||||||
final ArrayList<Subscription> varargSuperSubscriptions2 = getVarArgSuperSubscriptions_List(messageClass2, subManager);
|
// final ArrayList<Subscription> varargSuperSubscriptions2 = getVarArgSuperSubscriptions_List(messageClass2, subManager);
|
||||||
final ArrayList<Subscription> varargSuperSubscriptions3 = getVarArgSuperSubscriptions_List(messageClass3, subManager);
|
// final ArrayList<Subscription> varargSuperSubscriptions3 = getVarArgSuperSubscriptions_List(messageClass3, subManager);
|
||||||
|
//
|
||||||
subs = ClassUtils.findCommon(varargSuperSubscriptions1, varargSuperSubscriptions2);
|
// subs = ClassUtils.findCommon(varargSuperSubscriptions1, varargSuperSubscriptions2);
|
||||||
subs = ClassUtils.findCommon(subs, varargSuperSubscriptions3);
|
// subs = ClassUtils.findCommon(subs, varargSuperSubscriptions3);
|
||||||
|
//
|
||||||
subs.trimToSize();
|
// subs.trimToSize();
|
||||||
local.put(subs, messageClass1, messageClass2, messageClass3);
|
// local.put(subs, messageClass1, messageClass2, messageClass3);
|
||||||
}
|
// }
|
||||||
|
|
||||||
final Subscription[] returnedSubscriptions = new Subscription[subs.size()];
|
final Subscription[] returnedSubscriptions = new Subscription[subs.size()];
|
||||||
subs.toArray(returnedSubscriptions);
|
subs.toArray(returnedSubscriptions);
|
||||||
|
|
Loading…
Reference in New Issue
Block a user