No body concerned ? On 25 juil, 10:50, "[email protected]" <[email protected]> wrote: > Hi, > > I'm facing a problem when using the simple implementation of the > EventBus. > > // register widget B to be notified when WidgetA trigger an event > register handler of WidgetB on WidgetA.EventType > > // dispatch (firingDepth is incremented) > WidgetA.fireEvent > > // my widget is really called !!! that's good news > WidgetB.onWidgetAEvent > > // on the WidgetA.EventType reception is decided to create a widget C > create widgetC > > // this widget register himself to be notified on widgetB events -> > here the widget is registered in the deferredDeltas map (enqueueing) > register handler of widgetC on WidgetB.EventType > > // widget B fired an event which is never trapped by the widget C > because the handler of Widget C is in the deferredDeltas AND > firingDepth is not 0 > WidgetB.fireEvent > > I'm doubtful because I was expected Widget C to receive event from > Widget B. A work around is to encapsulate the WidgetB.fireEvent into a > DeferredCommand but it's not really a solution. > > An other solution is to reconsider the usage of firingDepth, I don't > really know why it is used (actually I know, but avoid concurrency > modification that way leads to the upper that strange behavior). > In simple implementation (thread safe) will be to get rid of the usage > of this firingDepth/deferredDeltas and that getHandlerList return a > copy of the handlers to go through and that's it: > We insert directly the handler when they request for registration and > we fire on the current map of handlers > > Below is a possible implementation of what I think is a better > implementation (behaviorally speaking) : > > package com.google.web.bindery.event.shared; > > import java.util.ArrayList; > import java.util.Collections; > import java.util.HashMap; > import java.util.HashSet; > import java.util.List; > import java.util.ListIterator; > import java.util.Map; > import java.util.Set; > > import com.google.web.bindery.event.shared.Event.Type; > > public class MySimpleEventBus extends EventBus { > > private final boolean isReverseOrder; > > /** > * Map of event type to map of event source to list of their > handlers. > */ > private final Map<Event.Type<?>, Map<Object, List<?>>> map = > new HashMap<Event.Type<?>, Map<Object, List<?>>>(); > > public MySimpleEventBus() { > this(false); > } > > /** > * Allows creation of an instance that fires its handlers in the > reverse of > * the order in which they were added, although filtered handlers > all fire > * before unfiltered handlers. > * <p> > * > * @deprecated This is a legacy feature, required by GWT's old > HandlerManager. > * Reverse order is not honored for handlers tied to a > specific > * event source (via {@link #addHandlerToSource}. > */ > @Deprecated > protected MySimpleEventBus(boolean fireInReverseOrder) { > isReverseOrder = fireInReverseOrder; > } > > @Override > public <H> HandlerRegistration addHandler(Type<H> type, H handler) > { > return doAdd(type, null, handler); > } > > @Override > public <H> HandlerRegistration addHandlerToSource(final > Event.Type<H> type, final Object source, > final H handler) { > if (source == null) { > throw new NullPointerException("Cannot add a handler with a > null source"); > } > > return doAdd(type, source, handler); > } > > @Override > public void fireEvent(Event<?> event) { > doFire(event, null); > } > > @Override > public void fireEventFromSource(Event<?> event, Object source) { > if (source == null) { > throw new NullPointerException("Cannot fire from a null > source"); > } > doFire(event, source); > } > > /** > * @deprecated required by legacy features in GWT's old > HandlerManager > */ > @Deprecated > protected <H> void doRemove(Event.Type<H> type, Object source, H > handler) { > doRemoveNow(type, source, handler); > } > > /** > * @deprecated required by legacy features in GWT's old > HandlerManager > */ > @Deprecated > protected <H> H getHandler(Event.Type<H> type, int index) { > assert index < getHandlerCount(type) : "handlers for " + > type.getClass() + " have size: " > + getHandlerCount(type) + " so do not have a handler at > index: " + index; > > List<H> l = getHandlerList(type, null); > return l.get(index); > } > > /** > * @deprecated required by legacy features in GWT's old > HandlerManager > */ > @Deprecated > protected int getHandlerCount(Event.Type<?> eventKey) { > return getHandlerList(eventKey, null).size(); > } > > /** > * @deprecated required by legacy features in GWT's old > HandlerManager > */ > @Deprecated > protected boolean isEventHandled(Event.Type<?> eventKey) { > return map.containsKey(eventKey); > } > > private <H> HandlerRegistration doAdd(final Event.Type<H> type, > final Object source, > final H handler) { > if (type == null) { > throw new NullPointerException("Cannot add a handler with a > null type"); > } > if (handler == null) { > throw new NullPointerException("Cannot add a null handler"); > } > > doAddNow(type, source, handler); > > return new HandlerRegistration() { > public void removeHandler() { > doRemove(type, source, handler); > } > }; > } > > private <H> void doAddNow(Event.Type<H> type, Object source, H > handler) { > List<H> l = ensureHandlerList(type, source); > l.add(handler); > } > > private <H> void doFire(Event<H> event, Object source) { > if (event == null) { > throw new NullPointerException("Cannot fire null event"); > } > try { > > if (source != null) { > event.setSource(source); > } > > List<H> handlers = getDispatchList(event.getAssociatedType(), > source); > Set<Throwable> causes = null; > > ListIterator<H> it = > isReverseOrder ? handlers.listIterator(handlers.size()) : > handlers.listIterator(); > while (isReverseOrder ? it.hasPrevious() : it.hasNext()) { > H handler = isReverseOrder ? it.previous() : it.next(); > > try { > event.dispatch(handler); > } catch (Throwable e) { > if (causes == null) { > causes = new HashSet<Throwable>(); > } > causes.add(e); > } > } > > if (causes != null) { > throw new UmbrellaException(causes); > } > } finally { > // no more to do > } > } > > private <H> void doRemoveNow(Event.Type<H> type, Object source, H > handler) { > List<H> l = getHandlerList(type, source); > > boolean removed = l.remove(handler); > assert removed : "redundant remove call"; > if (removed && l.isEmpty()) { > prune(type, source); > } > } > > private <H> List<H> ensureHandlerList(Event.Type<H> type, Object > source) { > Map<Object, List<?>> sourceMap = map.get(type); > if (sourceMap == null) { > sourceMap = new HashMap<Object, List<?>>(); > map.put(type, sourceMap); > } > > // safe, we control the puts. > @SuppressWarnings("unchecked") > List<H> handlers = (List<H>) sourceMap.get(source); > if (handlers == null) { > handlers = new ArrayList<H>(); > sourceMap.put(source, handlers); > } > > return handlers; > } > > /** > * Return a copy of handlers to dispatch event to > */ > private <H> List<H> getDispatchList(Event.Type<H> type, Object > source) { > List<H> directHandlers = getHandlerList(type, source); > if (source == null) { > return new ArrayList<H>(directHandlers); > } > > List<H> globalHandlers = getHandlerList(type, null); > > List<H> rtn = new ArrayList<H>(directHandlers); > rtn.addAll(globalHandlers); > return rtn; > } > > private <H> List<H> getHandlerList(Event.Type<H> type, Object > source) { > Map<Object, List<?>> sourceMap = map.get(type); > if (sourceMap == null) { > return Collections.emptyList(); > } > > // safe, we control the puts. > @SuppressWarnings("unchecked") > List<H> handlers = (List<H>) sourceMap.get(source); > if (handlers == null) { > return Collections.emptyList(); > } > > return handlers; > } > > private void prune(Event.Type<?> type, Object source) { > Map<Object, List<?>> sourceMap = map.get(type); > > List<?> pruned = sourceMap.remove(source); > > assert pruned != null : "Can't prune what wasn't there"; > assert pruned.isEmpty() : "Pruned unempty list!"; > > if (sourceMap.isEmpty()) { > map.remove(type); > } > } > > }
-- You received this message because you are subscribed to the Google Groups "Google Web Toolkit" 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/google-web-toolkit?hl=en.
