Mark and dispatch async events in asynchronous way
Mark asynchronous events in RAPEventBroker#constructEvent with a
property "rap.async.event".
Use UISynchronize#asyncExec in
RAPUIEventObjectSupplier/RAPUIEventHandler for the marked events.
506316: [e4] "EventAdmin Async Event Dispatcher Thread" can be blocked
by a UI thread
https://bugs.eclipse.org/bugs/show_bug.cgi?id=506316
Change-Id: Id740102f65d5dc00ed0430f7e8bbca99f6ba180b
diff --git a/bundles/org.eclipse.rap.e4/src/org/eclipse/rap/e4/internal/RAPEventBroker.java b/bundles/org.eclipse.rap.e4/src/org/eclipse/rap/e4/internal/RAPEventBroker.java
index 0987dee..6fdfe1c 100644
--- a/bundles/org.eclipse.rap.e4/src/org/eclipse/rap/e4/internal/RAPEventBroker.java
+++ b/bundles/org.eclipse.rap.e4/src/org/eclipse/rap/e4/internal/RAPEventBroker.java
@@ -29,20 +29,23 @@
import org.osgi.service.event.EventHandler;
public class RAPEventBroker implements IEventBroker {
- // TBD synchronization
+ // TBD synchronization
+
+ private static final String ASYNC_EVENT = "rap.async.event";
+
private Map<EventHandler, Collection<ServiceRegistration<?>>> registrations = new HashMap<EventHandler, Collection<ServiceRegistration<?>>>();
@Inject
Logger logger;
-
+
@Inject
@Optional
UISynchronize uiSync;
-
+
@Inject
@Named(E4Application.INSTANCEID)
String instanceId;
-
+
// This is a temporary code to ensure that bundle containing
// EventAdmin implementation is started. This code it to be removed once
// the proper method to start EventAdmin is added.
@@ -62,13 +65,13 @@
}
}
}
-
+
public RAPEventBroker() {
// placeholder
}
public boolean send(String topic, Object data) {
- Event event = constructEvent(topic, data);
+ Event event = constructEvent(topic, data, false);
EventAdmin eventAdmin = Activator.getDefault().getEventAdmin();
if (eventAdmin == null) {
logger.error(NLS.bind("No EventAdmin", event.toString()));
@@ -79,7 +82,7 @@
}
public boolean post(String topic, Object data) {
- Event event = constructEvent(topic, data);
+ Event event = constructEvent(topic, data, true);
EventAdmin eventAdmin = Activator.getDefault().getEventAdmin();
if (eventAdmin == null) {
logger.error(NLS.bind("No EventAdmin", event.toString()));
@@ -90,18 +93,26 @@
}
@SuppressWarnings("unchecked")
- private Event constructEvent(String topic, Object data) {
+ private Event constructEvent(String topic, Object data, boolean async) {
topic = rapifyTopic(instanceId, topic);
Event event;
if (data instanceof Dictionary<?,?>) {
- event = new Event(topic, (Dictionary<String,?>)data);
+ Dictionary<String,Object> properties = (Dictionary<String,Object>)data;
+ if (async)
+ properties.put(ASYNC_EVENT, Boolean.TRUE);
+ event = new Event(topic, properties);
} else if (data instanceof Map<?,?>) {
- event = new Event(topic, (Map<String,?>)data);
+ Map<String,Object> properties = (Map<String,Object>)data;
+ if (async)
+ properties.put(ASYNC_EVENT, Boolean.TRUE);
+ event = new Event(topic, properties);
} else {
- Dictionary<String, Object> d = new Hashtable<String, Object>(2);
+ Dictionary<String, Object> d = new Hashtable<String, Object>(3);
d.put(EventConstants.EVENT_TOPIC, topic);
if (data != null)
d.put(IEventBroker.DATA, data);
+ if (async)
+ d.put(ASYNC_EVENT, Boolean.TRUE);
event = new Event(topic, d);
}
return event;
@@ -110,7 +121,7 @@
public boolean subscribe(String topic, EventHandler eventHandler) {
return subscribe(topic, null, eventHandler, false);
}
-
+
public boolean subscribe(String topic, String filter, EventHandler eventHandler, boolean headless) {
topic = rapifyTopic(instanceId, topic);
BundleContext bundleContext = Activator.getDefault().getBundleContext();
@@ -146,7 +157,7 @@
}
return true;
}
-
+
@PreDestroy
void dispose() {
Collection<Collection<ServiceRegistration<?>>> values = new ArrayList<Collection<ServiceRegistration<?>>>(
@@ -160,10 +171,14 @@
}
}
}
-
+
public static String rapifyTopic(String instanceId, String topic) {
String rv = instanceId + "/" + topic;
// System.err.println("Original: " + topic + ", RAPified: " + rv);
return rv;
}
+
+ public static boolean isAsyncEvent(Event event) {
+ return Boolean.TRUE.equals(event.getProperty(ASYNC_EVENT));
+ }
}
diff --git a/bundles/org.eclipse.rap.e4/src/org/eclipse/rap/e4/internal/RAPUIEventHandler.java b/bundles/org.eclipse.rap.e4/src/org/eclipse/rap/e4/internal/RAPUIEventHandler.java
index 3fcf07a..a62d958 100644
--- a/bundles/org.eclipse.rap.e4/src/org/eclipse/rap/e4/internal/RAPUIEventHandler.java
+++ b/bundles/org.eclipse.rap.e4/src/org/eclipse/rap/e4/internal/RAPUIEventHandler.java
@@ -4,7 +4,7 @@
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
- *
+ *
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
@@ -19,15 +19,15 @@
* The helper will properly place UI-aware consumers on the main thread.
*/
public class RAPUIEventHandler implements EventHandler {
-
+
final private EventHandler eventHandler;
final private UISynchronize uiSync;
-
+
public RAPUIEventHandler(EventHandler eventHandler, UISynchronize uiSync) {
this.eventHandler = eventHandler;
this.uiSync = uiSync;
}
-
+
/* (non-Javadoc)
* @see org.osgi.service.event.EventHandler#handleEvent(org.osgi.service.event.Event)
*/
@@ -35,12 +35,19 @@
if (uiSync == null)
eventHandler.handleEvent(event);
else {
- uiSync.syncExec(new Runnable() {
-
- public void run() {
- eventHandler.handleEvent(event);
- }
- });
+ if(RAPEventBroker.isAsyncEvent(event)) {
+ uiSync.asyncExec(new Runnable() {
+ public void run() {
+ eventHandler.handleEvent(event);
+ }
+ });
+ } else {
+ uiSync.syncExec(new Runnable() {
+ public void run() {
+ eventHandler.handleEvent(event);
+ }
+ });
+ }
}
}
}
diff --git a/bundles/org.eclipse.rap.e4/src/org/eclipse/rap/e4/internal/RAPUIEventObjectSupplier.java b/bundles/org.eclipse.rap.e4/src/org/eclipse/rap/e4/internal/RAPUIEventObjectSupplier.java
index 10d2b99..c1eb2cb 100644
--- a/bundles/org.eclipse.rap.e4/src/org/eclipse/rap/e4/internal/RAPUIEventObjectSupplier.java
+++ b/bundles/org.eclipse.rap.e4/src/org/eclipse/rap/e4/internal/RAPUIEventObjectSupplier.java
@@ -34,18 +34,26 @@
logger.log(Level.WARNING, "No realm found to process UI event " + event);
return;
} else {
- uiSync.syncExec(new Runnable() {
- public void run() {
- requestor.execute();
- }
- });
+ if(RAPEventBroker.isAsyncEvent(event)) {
+ uiSync.asyncExec(new Runnable() {
+ public void run() {
+ requestor.execute();
+ }
+ });
+ } else {
+ uiSync.syncExec(new Runnable() {
+ public void run() {
+ requestor.execute();
+ }
+ });
+ }
}
- }
+ }
}
-
+
@Inject
protected UISynchronize uiSync;
-
+
@Inject @Optional
protected Logger logger;