Repository: cayenne Updated Branches: refs/heads/master 4d42e2679 -> 0b1ab617f
cleanup Project: http://git-wip-us.apache.org/repos/asf/cayenne/repo Commit: http://git-wip-us.apache.org/repos/asf/cayenne/commit/0b1ab617 Tree: http://git-wip-us.apache.org/repos/asf/cayenne/tree/0b1ab617 Diff: http://git-wip-us.apache.org/repos/asf/cayenne/diff/0b1ab617 Branch: refs/heads/master Commit: 0b1ab617f36bd5912eef7308afecbebdfc0f44ad Parents: 4d42e26 Author: Nikita Timofeev <stari...@gmail.com> Authored: Thu Jan 10 17:27:54 2019 +0300 Committer: Nikita Timofeev <stari...@gmail.com> Committed: Thu Jan 10 17:27:54 2019 +0300 ---------------------------------------------------------------------- .../cayenne/event/DefaultEventManager.java | 75 ++++------- .../org/apache/cayenne/event/DispatchQueue.java | 45 ++----- .../org/apache/cayenne/util/Invocation.java | 132 +++++++------------ 3 files changed, 86 insertions(+), 166 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cayenne/blob/0b1ab617/cayenne-server/src/main/java/org/apache/cayenne/event/DefaultEventManager.java ---------------------------------------------------------------------- diff --git a/cayenne-server/src/main/java/org/apache/cayenne/event/DefaultEventManager.java b/cayenne-server/src/main/java/org/apache/cayenne/event/DefaultEventManager.java index 7a5a9e3..9abba1e 100644 --- a/cayenne-server/src/main/java/org/apache/cayenne/event/DefaultEventManager.java +++ b/cayenne-server/src/main/java/org/apache/cayenne/event/DefaultEventManager.java @@ -37,14 +37,15 @@ import java.util.WeakHashMap; */ public class DefaultEventManager implements EventManager { - static final int DEFAULT_DISPATCH_THREAD_COUNT = 5; + private static final int DEFAULT_DISPATCH_THREAD_COUNT = 5; // keeps weak references to subjects - protected Map<EventSubject, DispatchQueue> subjects; - protected List<Dispatch> eventQueue; - protected boolean singleThread; + protected final Map<EventSubject, DispatchQueue> subjects; + protected final List<Dispatch> eventQueue; + protected final boolean singleThread; + protected final List<DispatchThread> dispatchThreads; + protected volatile boolean stopped; - List<DispatchThread> dispatchThreads; /** * Creates a multithreaded EventManager using default thread count. @@ -59,9 +60,8 @@ public class DefaultEventManager implements EventManager { * less. */ public DefaultEventManager(int dispatchThreadCount) { - this.subjects = Collections - .synchronizedMap(new WeakHashMap<EventSubject, DispatchQueue>()); - this.eventQueue = Collections.synchronizedList(new LinkedList<Dispatch>()); + this.subjects = Collections.synchronizedMap(new WeakHashMap<>()); + this.eventQueue = Collections.synchronizedList(new LinkedList<>()); this.singleThread = dispatchThreadCount <= 0; if (!singleThread) { @@ -75,8 +75,7 @@ public class DefaultEventManager implements EventManager { dispatchThreads.add(thread); thread.start(); } - } - else { + } else { dispatchThreads = Collections.emptyList(); } } @@ -143,8 +142,7 @@ public class DefaultEventManager implements EventManager { EventSubject subject) { if (singleThread) { - throw new IllegalStateException( - "DefaultEventManager is configured to be single-threaded."); + throw new IllegalStateException("DefaultEventManager is configured to be single-threaded."); } this.addListener(listener, methodName, eventParameterClass, subject, null, false); @@ -179,8 +177,7 @@ public class DefaultEventManager implements EventManager { Object sender) { if (singleThread) { - throw new IllegalStateException( - "DefaultEventManager is configured to be single-threaded."); + throw new IllegalStateException("DefaultEventManager is configured to be single-threaded."); } addListener(listener, methodName, eventParameterClass, subject, sender, false); @@ -207,18 +204,12 @@ public class DefaultEventManager implements EventManager { } try { - Invocation invocation = (blocking) ? new Invocation( - listener, - methodName, - eventParameterClass) : new NonBlockingInvocation( - listener, - methodName, - eventParameterClass); + Invocation invocation = blocking + ? new Invocation(listener, methodName, eventParameterClass) + : new NonBlockingInvocation(listener, methodName, eventParameterClass); dispatchQueueForSubject(subject, true).addInvocation(invocation, sender); - } - catch (NoSuchMethodException nsm) { - throw new CayenneRuntimeException("Error adding listener, method name: " - + methodName, nsm); + } catch (NoSuchMethodException nsm) { + throw new CayenneRuntimeException("Error adding listener, method name: %s", nsm, methodName); } } @@ -322,8 +313,7 @@ public class DefaultEventManager implements EventManager { */ public void postNonBlockingEvent(EventObject event, EventSubject subject) { if (singleThread) { - throw new IllegalStateException( - "EventManager is configured to be single-threaded."); + throw new IllegalStateException("EventManager is configured to be single-threaded."); } // add dispatch to the queue and return @@ -359,9 +349,7 @@ public class DefaultEventManager implements EventManager { EventSubject subject; Dispatch(EventObject event, EventSubject subject) { - this(new EventObject[] { - event - }, subject); + this(new EventObject[] {event}, subject); } Dispatch(EventObject[] eventArgument, EventSubject subject) { @@ -387,16 +375,12 @@ public class DefaultEventManager implements EventManager { // inject single invocation dispatch into the queue synchronized (eventQueue) { - eventQueue.add(new InvocationDispatch( - eventArgument, - subject, - invocation)); + eventQueue.add(new InvocationDispatch(eventArgument, subject, invocation)); eventQueue.notifyAll(); } return true; - } - else { + } else { return invocation.fire(eventArgument); } } @@ -407,8 +391,7 @@ public class DefaultEventManager implements EventManager { Invocation target; - InvocationDispatch(EventObject[] eventArgument, EventSubject subject, - Invocation target) { + InvocationDispatch(EventObject[] eventArgument, EventSubject subject, Invocation target) { super(eventArgument, subject); this.target = target; } @@ -424,9 +407,7 @@ public class DefaultEventManager implements EventManager { // subclass exists only to tag invocations that should be // dispatched in a separate thread final class NonBlockingInvocation extends Invocation { - - public NonBlockingInvocation(Object target, String methodName, - Class<?> parameterType) throws NoSuchMethodException { + NonBlockingInvocation(Object target, String methodName, Class<?> parameterType) throws NoSuchMethodException { super(target, methodName, parameterType); } } @@ -442,20 +423,17 @@ public class DefaultEventManager implements EventManager { public void run() { while (!stopped) { - // get event from the queue, if the queue - // is empty, just wait + // get event from the queue, if the queue is empty, just wait Dispatch dispatch = null; synchronized (DefaultEventManager.this.eventQueue) { if (DefaultEventManager.this.eventQueue.size() > 0) { dispatch = DefaultEventManager.this.eventQueue.remove(0); - } - else { + } else { try { // wake up occasionally to check whether EM has been stopped DefaultEventManager.this.eventQueue.wait(3 * 60 * 1000); - } - catch (InterruptedException e) { + } catch (InterruptedException e) { // ignore interrupts... } } @@ -467,8 +445,7 @@ public class DefaultEventManager implements EventManager { // from dying on dispatch errors try { dispatch.fire(); - } - catch (Throwable th) { + } catch (Throwable th) { // ignoring exception } } http://git-wip-us.apache.org/repos/asf/cayenne/blob/0b1ab617/cayenne-server/src/main/java/org/apache/cayenne/event/DispatchQueue.java ---------------------------------------------------------------------- diff --git a/cayenne-server/src/main/java/org/apache/cayenne/event/DispatchQueue.java b/cayenne-server/src/main/java/org/apache/cayenne/event/DispatchQueue.java index 67df081..5034a72 100644 --- a/cayenne-server/src/main/java/org/apache/cayenne/event/DispatchQueue.java +++ b/cayenne-server/src/main/java/org/apache/cayenne/event/DispatchQueue.java @@ -43,11 +43,10 @@ class DispatchQueue { private final Map<Object, ConcurrentMap<Invocation, Object>> invocationsBySender; DispatchQueue() { - subjectInvocations = new ConcurrentHashMap<Invocation, Object>(); + subjectInvocations = new ConcurrentHashMap<>(); - // TODO: need something like com.google.common.collect.MapMaker to avoid - // synchronization on invocationsBySender - invocationsBySender = new WeakHashMap<Object, ConcurrentMap<Invocation, Object>>(); + // TODO: need something like com.google.common.collect.MapMaker to avoid synchronization on invocationsBySender + invocationsBySender = new WeakHashMap<>(); } /** @@ -71,8 +70,7 @@ class DispatchQueue { if (sender == null) { invocations = subjectInvocations; - } - else { + } else { invocations = invocationsForSender(sender, true); } @@ -80,14 +78,7 @@ class DispatchQueue { // result in a memory leak per CAY-770. This seemed to happen when lots of // invocations got registered, but no events were dispatched (hence the stale // invocation removal during dispatch did not happen) - Iterator<Invocation> it = invocations.keySet().iterator(); - while (it.hasNext()) { - Invocation i = it.next(); - if (i.getTarget() == null) { - it.remove(); - } - } - + invocations.keySet().removeIf(i -> i.getTarget() == null); invocations.putIfAbsent(invocation, Boolean.TRUE); } @@ -102,8 +93,7 @@ class DispatchQueue { boolean didRemove = removeInvocations(subjectInvocations, listener); synchronized (invocationsBySender) { - for (ConcurrentMap<Invocation, Object> senderInvocations : invocationsBySender - .values()) { + for (ConcurrentMap<Invocation, Object> senderInvocations : invocationsBySender.values()) { didRemove = removeInvocations(senderInvocations, listener) || didRemove; } } @@ -111,16 +101,12 @@ class DispatchQueue { return didRemove; } - private ConcurrentMap<Invocation, Object> invocationsForSender( - Object sender, - boolean create) { + private ConcurrentMap<Invocation, Object> invocationsForSender(Object sender, boolean create) { synchronized (invocationsBySender) { - - ConcurrentMap<Invocation, Object> senderInvocations = invocationsBySender - .get(sender); + ConcurrentMap<Invocation, Object> senderInvocations = invocationsBySender.get(sender); if (create && senderInvocations == null) { - senderInvocations = new ConcurrentHashMap<Invocation, Object>(); + senderInvocations = new ConcurrentHashMap<>(); invocationsBySender.put(sender, senderInvocations); } @@ -152,16 +138,7 @@ class DispatchQueue { // dispatches event to a list of listeners private void dispatchEvent(Collection<Invocation> invocations, Dispatch dispatch) { - - Iterator<Invocation> it = invocations.iterator(); - while (it.hasNext()) { - - // fire invocation, clean up GC'd invocations... - - Invocation invocation = it.next(); - if (!dispatch.fire(invocation)) { - it.remove(); - } - } + // fire invocation, clean up GC'd invocations... + invocations.removeIf(invocation -> !dispatch.fire(invocation)); } } http://git-wip-us.apache.org/repos/asf/cayenne/blob/0b1ab617/cayenne-server/src/main/java/org/apache/cayenne/util/Invocation.java ---------------------------------------------------------------------- diff --git a/cayenne-server/src/main/java/org/apache/cayenne/util/Invocation.java b/cayenne-server/src/main/java/org/apache/cayenne/util/Invocation.java index 23a6fdf..eb9e7da 100644 --- a/cayenne-server/src/main/java/org/apache/cayenne/util/Invocation.java +++ b/cayenne-server/src/main/java/org/apache/cayenne/util/Invocation.java @@ -34,9 +34,9 @@ import org.apache.cayenne.CayenneRuntimeException; */ public class Invocation { - private WeakReference _target; - private Method _method; - private Class[] _parameterTypes; + private WeakReference<?> target; + private Method method; + private Class<?>[] parameterTypes; /** * Prevent use of empty default constructor @@ -58,28 +58,18 @@ public class Invocation { * * @see #Invocation(Object, String, Class[]) */ - public Invocation(Object target, String methodName, Class parameterType) - throws NoSuchMethodException { - this(target, methodName, new Class[] { - parameterType - }); + public Invocation(Object target, String methodName, Class parameterType) throws NoSuchMethodException { + this(target, methodName, new Class[] {parameterType}); } /** * Constructor for an Invocation with arbitrary arguments in the target's method. * - * @param target - * @param methodName - * @param parameterTypes - * @throws NoSuchMethodException if <code>methodName</code> could not be found in - * the target + * @throws NoSuchMethodException if <code>methodName</code> could not be found in the target * @throws IllegalArgumentException if target or methodName are <code>null</code>, * or parameterTypes is empty or contains <code>null</code> elements */ - public Invocation(Object target, String methodName, Class[] parameterTypes) - throws NoSuchMethodException { - super(); - + public Invocation(Object target, String methodName, Class[] parameterTypes) throws NoSuchMethodException { if (target == null) { throw new IllegalArgumentException("target argument must not be null"); } @@ -92,13 +82,10 @@ public class Invocation { if (parameterTypes.length > 0) { for (int i = 0; i < parameterTypes.length; i++) { if (parameterTypes[i] == null) { - throw new IllegalArgumentException("parameter type[" - + i - + "] must not be null"); + throw new IllegalArgumentException("parameter type[" + i + "] must not be null"); } } - } - else { + } else { throw new IllegalArgumentException("parameter types must not be empty"); } } @@ -106,32 +93,23 @@ public class Invocation { // allow access to public methods of inaccessible classes, if such methods were // declared in a public interface - _method = lookupMethodInHierarchy(target.getClass(), methodName, parameterTypes); - - if (_method == null) { - throw new NoSuchMethodException("No such method: " - + target.getClass().getName() - + "." - + methodName); + method = lookupMethodInHierarchy(target.getClass(), methodName, parameterTypes); + if (method == null) { + throw new NoSuchMethodException("No such method: " + target.getClass().getName() + "." + methodName); } - - if (!Util.isAccessible(_method)) { - _method.setAccessible(true); + if (!Util.isAccessible(method)) { + method.setAccessible(true); } - _parameterTypes = parameterTypes; - _target = new WeakReference(target); + this.parameterTypes = parameterTypes; + this.target = new WeakReference<>(target); } - Method lookupMethodInHierarchy( - Class objectClass, - String methodName, - Class[] parameterTypes) throws SecurityException, NoSuchMethodException { - + Method lookupMethodInHierarchy(Class<?> objectClass, String methodName, Class[] parameterTypes) + throws SecurityException, NoSuchMethodException { try { return objectClass.getDeclaredMethod(methodName, parameterTypes); - } - catch (NoSuchMethodException e) { + } catch (NoSuchMethodException e) { Class superClass = objectClass.getSuperclass(); if (superClass == null || superClass.getName().equals(Object.class.getName())) { @@ -158,9 +136,7 @@ public class Invocation { * @see #fire(Object[]) */ public boolean fire(Object argument) { - return this.fire(new Object[] { - argument - }); + return this.fire(new Object[] {argument}); } /** @@ -177,32 +153,29 @@ public class Invocation { */ public boolean fire(Object[] arguments) { - if (_parameterTypes == null) { + if (parameterTypes == null) { if (arguments != null) { throw new IllegalArgumentException("arguments unexpectedly != null"); } - } - else if (arguments == null) { + } else if (arguments == null) { throw new IllegalArgumentException("arguments must not be null"); - } - else if (_parameterTypes.length != arguments.length) { + } else if (parameterTypes.length != arguments.length) { throw new IllegalArgumentException( "inconsistent number of arguments: expected" - + _parameterTypes.length + + parameterTypes.length + ", got " + arguments.length); } - Object currentTarget = _target.get(); + Object currentTarget = target.get(); if (currentTarget == null) { return false; } try { - _method.invoke(currentTarget, arguments); + method.invoke(currentTarget, arguments); return true; - } - catch (InvocationTargetException ite) { + } catch (InvocationTargetException ite) { // this is the only type of exception that can be rethrown, since // listener can have a valid need to respond to an event with exception, // and this does not indicate that it is being in invalid state @@ -210,12 +183,10 @@ public class Invocation { Throwable cause = ite.getCause(); if (cause instanceof RuntimeException) { throw (RuntimeException) cause; - } - else { + } else { throw new CayenneRuntimeException(cause); } - } - catch (Exception ex) { + } catch (Exception ex) { // all other exceptions indicate propblems with the listener, // so return invalid status return false; @@ -227,30 +198,27 @@ public class Invocation { */ @Override public boolean equals(Object obj) { - if ((obj != null) && (obj.getClass().equals(this.getClass()))) { - Invocation otherInvocation = (Invocation) obj; - if (_method.equals(otherInvocation.getMethod())) { - Object otherTarget = otherInvocation.getTarget(); - Object target = _target.get(); - - if ((target == null) && (otherTarget == null)) { - return true; - } + if (obj == null || !obj.getClass().equals(this.getClass())) { + return false; + } - if ((target == null) && (otherTarget != null)) { - return false; - } + Invocation otherInvocation = (Invocation) obj; + if (!method.equals(otherInvocation.getMethod())) { + return false; + } - if (target != null) { - return target.equals(otherTarget); - } - } + Object otherTarget = otherInvocation.getTarget(); + Object target = this.getTarget(); - return false; + if (target == otherTarget) { + return true; } - else { - return super.equals(obj); + + if (target == null) { + return false; } + + return target.equals(otherTarget); } /** @@ -264,30 +232,28 @@ public class Invocation { // hashCode, and breaking collections using Invocation as a key // (e.g. event DispatchQueue) - // TODO: use Jakarta commons HashBuilder - int hash = 42, hashMultiplier = 59; - return hash * hashMultiplier + _method.hashCode(); + return method.hashCode(); } /** * @return the method to be invoked on the target */ public Method getMethod() { - return _method; + return method; } /** * @return the target object of this Invocation */ public Object getTarget() { - return _target.get(); + return target.get(); } /** * @return an array of Classes describing the target method's parameters */ public Class[] getParameterTypes() { - return _parameterTypes; + return parameterTypes; } }