Author: mes
Date: 2011-06-20 17:07:29 -0700 (Mon, 20 Jun 2011)
New Revision: 25825
Modified:
core3/event-api/branches/nagling-events/src/main/java/org/cytoscape/event/AbstractCyEvent.java
core3/event-api/branches/nagling-events/src/main/java/org/cytoscape/event/AbstractCyPayloadEvent.java
core3/event-api/branches/nagling-events/src/main/java/org/cytoscape/event/CyEventHelper.java
core3/event-api/branches/nagling-events/src/main/java/org/cytoscape/event/CyPayloadEvent.java
core3/event-api/branches/nagling-events/src/test/java/org/cytoscape/event/AbstractCyEventHelperTest.java
core3/event-api/branches/nagling-events/src/test/java/org/cytoscape/event/AbstractCyPayloadEventTest.java
core3/event-api/branches/nagling-events/src/test/java/org/cytoscape/event/StubCyPayloadListenerImpl.java
core3/event-impl/branches/nagling-events/impl/src/main/java/org/cytoscape/event/internal/CyEventHelperImpl.java
core3/event-impl/branches/nagling-events/impl/src/main/java/org/cytoscape/event/internal/CyListenerAdapter.java
Log:
Lots of cleanup
Modified:
core3/event-api/branches/nagling-events/src/main/java/org/cytoscape/event/AbstractCyEvent.java
===================================================================
---
core3/event-api/branches/nagling-events/src/main/java/org/cytoscape/event/AbstractCyEvent.java
2011-06-20 23:15:01 UTC (rev 25824)
+++
core3/event-api/branches/nagling-events/src/main/java/org/cytoscape/event/AbstractCyEvent.java
2011-06-21 00:07:29 UTC (rev 25825)
@@ -47,7 +47,6 @@
* Constructor.
* @param source The source object that fires the event. May NOT be
null.
* @param listenerClass The Class that defines the listener interface.
May NOT be null.
- * @param synchronousOnly Whether the event may only be fired
synchronously.
*/
public AbstractCyEvent(final T source, Class<?> listenerClass) {
if ( source == null )
Modified:
core3/event-api/branches/nagling-events/src/main/java/org/cytoscape/event/AbstractCyPayloadEvent.java
===================================================================
---
core3/event-api/branches/nagling-events/src/main/java/org/cytoscape/event/AbstractCyPayloadEvent.java
2011-06-20 23:15:01 UTC (rev 25824)
+++
core3/event-api/branches/nagling-events/src/main/java/org/cytoscape/event/AbstractCyPayloadEvent.java
2011-06-21 00:07:29 UTC (rev 25825)
@@ -35,6 +35,7 @@
package org.cytoscape.event;
import java.util.Collection;
+import java.util.Collections;
/**
* A base implementation of CyPayloadEvent that can be used by events.
@@ -43,17 +44,24 @@
private final Collection<P> payload;
+ /**
+ * Constructor.
+ * @param source The event source object.
+ * @param listenerClass The listener class for this event.
+ * @param payload A collection of payload objects. May be empty, but
not null!
+ */
public AbstractCyPayloadEvent(final T source, Class<?> listenerClass,
Collection<P> payload) {
super(source, listenerClass);
if ( payload == null )
throw new NullPointerException("Payload is null");
- this.payload = payload;
+ this.payload = Collections.unmodifiableCollection(payload);
}
/**
- * {@inheritDoc}
+ * Returns an unmodifiable collection of payload objects.
+ * @return an unmodifiable collection of payload objects.
*/
@Override
public Collection<P> getPayloadCollection() {
Modified:
core3/event-api/branches/nagling-events/src/main/java/org/cytoscape/event/CyEventHelper.java
===================================================================
---
core3/event-api/branches/nagling-events/src/main/java/org/cytoscape/event/CyEventHelper.java
2011-06-20 23:15:01 UTC (rev 25824)
+++
core3/event-api/branches/nagling-events/src/main/java/org/cytoscape/event/CyEventHelper.java
2011-06-21 00:07:29 UTC (rev 25825)
@@ -38,7 +38,7 @@
* The default number of milliseconds to wait before the next
* time that we will check for payload events to fire.
*/
- int DEFAULT_PAYLOAD_WAIT_TIME_MILLIS = 100;
+ int DEFAULT_PAYLOAD_INTERVAL_MILLIS = 100;
/**
* Calls each listener found in the Service Registry identified by the
listenerClass
@@ -50,11 +50,12 @@
<E extends CyEvent<?>> void fireEvent(final E event);
/**
- * Adds a payload object to be accumulated in an event. The event is
guaranteed
+ * Adds a payload object to be accumulated in a CyPayloadEvent. The
event is guaranteed
* to be fired after a certain duration where the single event contains
all payload
* objects added to the event within that window of time. Payload
objects added
* after an event has fired simply trigger a new event to fire at the
next time
- * point.
+ * point. All accumulated CyPayloadEvents are guaranteed to be fired
before any
+ * normal CyEvents are fired.
* @param source The object firing the event.
* @param payload The data payload to be added to the event that will
* eventually be fired.
Modified:
core3/event-api/branches/nagling-events/src/main/java/org/cytoscape/event/CyPayloadEvent.java
===================================================================
---
core3/event-api/branches/nagling-events/src/main/java/org/cytoscape/event/CyPayloadEvent.java
2011-06-20 23:15:01 UTC (rev 25824)
+++
core3/event-api/branches/nagling-events/src/main/java/org/cytoscape/event/CyPayloadEvent.java
2011-06-21 00:07:29 UTC (rev 25825)
@@ -37,7 +37,16 @@
import java.util.Collection;
-public interface CyPayloadEvent<T,P> extends CyEvent<T> {
+/**
+ * An extension of CyEvent specifically for payload events.
+ * @param <S> The event source type.
+ * @param <P> The payload type.
+ */
+public interface CyPayloadEvent<S,P> extends CyEvent<S> {
+ /**
+ * Returns a collection of payload objects.
+ * @return a collection of payload objects.
+ */
Collection<P> getPayloadCollection();
}
Modified:
core3/event-api/branches/nagling-events/src/test/java/org/cytoscape/event/AbstractCyEventHelperTest.java
===================================================================
---
core3/event-api/branches/nagling-events/src/test/java/org/cytoscape/event/AbstractCyEventHelperTest.java
2011-06-20 23:15:01 UTC (rev 25824)
+++
core3/event-api/branches/nagling-events/src/test/java/org/cytoscape/event/AbstractCyEventHelperTest.java
2011-06-21 00:07:29 UTC (rev 25825)
@@ -68,7 +68,7 @@
// We verify that the payload approach is at least 3 times faster than
the
// event/listener combo.
@Test
- public void testLD1second() {
+ public void testLD1fifthsecond() {
final long duration = 200000000;
long end = System.nanoTime() + duration;
@@ -212,4 +212,15 @@
assertTrue( payloadService.getNumCalls() > 1 );
} catch ( InterruptedException ie ) { throw new
RuntimeException(ie); }
}
+
+ @Test
+ public void testPayloadBeforeNormal() {
+
helper.addEventPayload("source","homer",StubCyPayloadEvent.class);
+
helper.addEventPayload("source","marge",StubCyPayloadEvent.class);
+ helper.fireEvent(new StubCyEvent("lisa"));
+ // This tests that any accumulated payload events get fired
before
+ // normal events.
+ assertTrue(payloadService.getNumCalls() == 1);
+ assertTrue(service.getNumCalls() == 1);
+ }
}
Modified:
core3/event-api/branches/nagling-events/src/test/java/org/cytoscape/event/AbstractCyPayloadEventTest.java
===================================================================
---
core3/event-api/branches/nagling-events/src/test/java/org/cytoscape/event/AbstractCyPayloadEventTest.java
2011-06-20 23:15:01 UTC (rev 25824)
+++
core3/event-api/branches/nagling-events/src/test/java/org/cytoscape/event/AbstractCyPayloadEventTest.java
2011-06-21 00:07:29 UTC (rev 25825)
@@ -85,4 +85,15 @@
assertEquals(0,payload.size());
assertFalse(payload.contains("bart"));
}
+
+ @Test(expected=UnsupportedOperationException.class)
+ public void testCantModifyPayload() {
+ List<String> l = new ArrayList<String>();
+ l.add("homer");
+ l.add("marge");
+ Object source = new Object();
+ TestEvent<Object,String> e = new
TestEvent<Object,String>(source,Object.class,l);
+ Collection<String> payload = e.getPayloadCollection();
+ payload.add("something");
+ }
}
Modified:
core3/event-api/branches/nagling-events/src/test/java/org/cytoscape/event/StubCyPayloadListenerImpl.java
===================================================================
---
core3/event-api/branches/nagling-events/src/test/java/org/cytoscape/event/StubCyPayloadListenerImpl.java
2011-06-20 23:15:01 UTC (rev 25824)
+++
core3/event-api/branches/nagling-events/src/test/java/org/cytoscape/event/StubCyPayloadListenerImpl.java
2011-06-21 00:07:29 UTC (rev 25825)
@@ -49,15 +49,9 @@
* @param e DOCUMENT ME!
*/
public void handleEvent(StubCyPayloadEvent e) {
-// System.out.println("begin handle payload in thread " +
Thread.currentThread());
-// for (String payload : e.getPayloadCollection()) {
-// System.out.print(payload + " ");
-// }
-// System.out.println("");
called++;
if ( eh != null ) {
for ( int i = 0; i < 5; i++ ) {
-// System.out.println("adding additional event
payloads..." + i);
try { Thread.sleep(100); } catch (Exception ex)
{}
eh.addEventPayload("listener","payload"+i,StubCyPayloadEvent.class);
}
Modified:
core3/event-impl/branches/nagling-events/impl/src/main/java/org/cytoscape/event/internal/CyEventHelperImpl.java
===================================================================
---
core3/event-impl/branches/nagling-events/impl/src/main/java/org/cytoscape/event/internal/CyEventHelperImpl.java
2011-06-20 23:15:01 UTC (rev 25824)
+++
core3/event-impl/branches/nagling-events/impl/src/main/java/org/cytoscape/event/internal/CyEventHelperImpl.java
2011-06-21 00:07:29 UTC (rev 25825)
@@ -67,35 +67,33 @@
private boolean havePayload;
public CyEventHelperImpl(final CyListenerAdapter normal) {
-
//System.out.println("\n\n===================================================================================\n\n");
this.normal = normal;
-
sourceAccMap = new
HashMap<Object,Map<Class<?>,PayloadAccumulator<?,?,?>>>();
-
payloadEventMonitor =
Executors.newSingleThreadScheduledExecutor();
-
silencedSources = new HashSet<Object>();
-
havePayload = false;
- final Runnable firingAgent = new Runnable() {
+ // This thread just flushes any accumulated payload events.
+ // It is scheduled to run repeatedly at a fixed interval.
+ final Runnable payloadChecker = new Runnable() {
public void run() {
- final int x = new Random().nextInt();
- //System.out.println("*************** begin firing check
************* " + x + " " + Thread.currentThread() + " " + havePayload + "
" + System.currentTimeMillis() + " " + CyEventHelperImpl.this.hashCode() + "
" + this.hashCode());
flushPayloadEvents();
- //System.out.println("*************** end firing check
*************** " + x + " " + Thread.currentThread());
}
};
- payloadEventMonitor.scheduleAtFixedRate(firingAgent,
CyEventHelper.DEFAULT_PAYLOAD_WAIT_TIME_MILLIS,
CyEventHelper.DEFAULT_PAYLOAD_WAIT_TIME_MILLIS, TimeUnit.MILLISECONDS);
+ payloadEventMonitor.scheduleAtFixedRate(payloadChecker,
CyEventHelper.DEFAULT_PAYLOAD_INTERVAL_MILLIS,
CyEventHelper.DEFAULT_PAYLOAD_INTERVAL_MILLIS, TimeUnit.MILLISECONDS);
}
@Override
public <E extends CyEvent<?>> void fireEvent(final E event) {
- //System.out.println("firing event: " + event);
+ // Before any external event is fired, flush any accumulated
+ // payload events. Because addEventPayload() in synchronous,
+ // all payloads should be added by the time fireEvent() is
+ // called in the client code.
+ flushPayloadEvents();
+
normal.fireEvent(event);
}
-
@Override
public void silenceEventSource(Object eventSource) {
if ( eventSource == null )
@@ -147,8 +145,6 @@
acc.addPayload(payload);
havePayload = true;
-
- //System.out.println("addEventPayload: " + source + "
" + payload + " " + eventType + " " + Thread.currentThread() + " " +
havePayload + " " + System.currentTimeMillis());
}
}
@@ -156,22 +152,18 @@
List<CyPayloadEvent<?,?>> flushList;
synchronized (this) {
- //System.out.println("trying forceFirePayloadEvents in
thread: " + Thread.currentThread() + " " + havePayload);
+
if ( !havePayload )
return;
flushList = new ArrayList<CyPayloadEvent<?,?>>();
havePayload = false;
- //System.out.println("forceFirePayloadEvents in thread:
" + Thread.currentThread());
for ( Object source : sourceAccMap.keySet() ) {
- //System.out.println(" examining source: " +
source);
for ( PayloadAccumulator<?,?,?> acc :
sourceAccMap.get(source).values() ) {
- //System.out.println(" found
accumulator: " + acc);
try {
CyPayloadEvent<?,?> event =
acc.newEventInstance( source );
if ( event != null ) {
-
//System.out.println("adding event to flush list " + event);
flushList.add(event);
}
} catch (Exception ie) {
@@ -180,15 +172,16 @@
}
}
- //System.out.println("forceFirePayloadEvents finished
collecting events: " + Thread.currentThread() + " " + havePayload);
}
+ // Actually fire the events outside of the synchronized block.
for (CyPayloadEvent<?,?> event : flushList) {
- //System.out.println("-----------force firing event: "
+ event);
- fireEvent(event);
+ normal.fireEvent(event);
}
}
+ // Used only for unit testing to prevent the confusion of multiple
+ // threads running at once.
public void cleanup() {
payloadEventMonitor.shutdown();
}
Modified:
core3/event-impl/branches/nagling-events/impl/src/main/java/org/cytoscape/event/internal/CyListenerAdapter.java
===================================================================
---
core3/event-impl/branches/nagling-events/impl/src/main/java/org/cytoscape/event/internal/CyListenerAdapter.java
2011-06-20 23:15:01 UTC (rev 25824)
+++
core3/event-impl/branches/nagling-events/impl/src/main/java/org/cytoscape/event/internal/CyListenerAdapter.java
2011-06-21 00:07:29 UTC (rev 25825)
@@ -50,7 +50,6 @@
*/
public class CyListenerAdapter {
private static final Logger logger =
LoggerFactory.getLogger(CyListenerAdapter.class);
- private static final Executor EXEC = Executors.newCachedThreadPool();
private static final ServiceComparator serviceComparator = new
ServiceComparator();
private final Map<Class<?>,ServiceTracker> serviceTrackers;
@@ -85,21 +84,11 @@
final Class<?> listenerClass = event.getListenerClass();
final Object[] listeners = getListeners(listenerClass);
- if ( listeners == null ) {
+ if ( listeners == null )
return;
- }
-
- // if ( event.synchronousOnly() )
- fireSynchronousEvent(event,listenerClass,listeners);
- // else
- // fireAsynchronousEvent(event,listenerClass,listeners);
- }
-
-
-
- private <E extends CyEvent<?>> void fireSynchronousEvent(final E event,
Class<?> listenerClass, Object[] listeners) {
-
+
Object lastListener = null;
+
try {
final Method method =
listenerClass.getMethod("handleEvent", event.getClass());
@@ -121,30 +110,6 @@
}
}
- /**
- * Calls each listener found in the Service Registry identified by the
listenerClass
- * and filter with the supplied event in a new thread.<p>This method
should <b>ONLY</b>
- * ever be called with a thread safe event object!</p>
- *
- * @param <E> The type of event.
- * @param event The event object.
- */
- private <E extends CyEvent> void fireAsynchronousEvent(final E event,
Class<?> listenerClass, Object[] listeners) {
-
-
- try {
- final Method method =
listenerClass.getMethod("handleEvent", event.getClass());
-
- for (final Object listener : listeners) {
- EXEC.execute(new Runner(method, listener,
event, listenerClass));
- }
- } catch (NoSuchMethodException e) {
- // TODO should probably rethrow
- logger.error("Listener doesn't implement
\"handleEvent\" method: "
- + listenerClass.getName(), e);
- }
- }
-
private Object[] getListeners(Class<?> listenerClass) {
if ( !serviceTrackers.containsKey( listenerClass ) ) {
//logger.debug("added new service tracker for " +
listenerClass);
@@ -170,30 +135,4 @@
silencedSources.remove(eventSource);
}
-
- private static class Runner implements Runnable {
- private final Method method;
- private final Object listener;
- private final Object event;
- private final Class clazz;
-
- public Runner(final Method method, final Object listener, final
Object event, Class clazz) {
- this.method = method;
- this.listener = listener;
- this.event = event;
- this.clazz = clazz;
- }
-
- public void run() {
- try {
- method.invoke(clazz.cast(listener), event);
- } catch (IllegalAccessException e) {
- // TODO should rethrow as something
- logger.error("Listener can't execute
\"handleEvent\" method: " + clazz.getName(), e);
- } catch (InvocationTargetException e) {
- // TODO should rethrow as something
- logger.error("Listener threw exception as part
of \"handleEvent\" invocation: " + listener.toString(), e);
- }
- }
- }
}
--
You received this message because you are subscribed to the Google Groups
"cytoscape-cvs" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to
[email protected].
For more options, visit this group at
http://groups.google.com/group/cytoscape-cvs?hl=en.