Author: [EMAIL PROTECTED]
Date: Thu Nov 13 20:22:40 2008
New Revision: 4072

Modified:
     
branches/1_6_clean_events/user/src/com/google/gwt/event/shared/HandlerManager.java

Log:
As initial benchmarks are leaning towards the desire to include the more  
complicated handler registry, it seems reasonably safe to add it back in.

Modified:  
branches/1_6_clean_events/user/src/com/google/gwt/event/shared/HandlerManager.java
==============================================================================
---  
branches/1_6_clean_events/user/src/com/google/gwt/event/shared/HandlerManager.java
       
(original)
+++  
branches/1_6_clean_events/user/src/com/google/gwt/event/shared/HandlerManager.java
       
Thu Nov 13 20:22:40 2008
@@ -15,6 +15,8 @@
   */
  package com.google.gwt.event.shared;

+import com.google.gwt.core.client.GWT;
+import com.google.gwt.core.client.JavaScriptObject;
  import com.google.gwt.event.shared.GwtEvent.Type;
  import com.google.gwt.user.client.Command;

@@ -81,10 +83,182 @@
      }
    }

+  /**
+   * Default JavaScript handler registry. This is in the shared class but  
should
+   * never be called outside of a GWT runtime environment.
+   *
+   * The JsHandlerRegistry makes use of the fact that in the large  
majority of
+   * cases, only one or two handlers are added for each event type.  
Therefore,
+   * rather than storing handlers in a list of lists, we store then in a  
single
+   * flattened array with an escape clause to handle the rare case where  
we have
+   * more handlers then expected.
+   */
+  private static class JsHandlerRegistry extends JavaScriptObject {
+
+    /**
+     * Required constructor.
+     */
+    protected JsHandlerRegistry() {
+    }
+
+    public final <H extends EventHandler> void addHandler(
+        Type<H> type, H myHandler) {
+
+      // The base is the equivalent to a c pointer into the flattened  
handler
+      // data structure.
+      int base = type.hashCode();
+      int count = getCount(base);
+      boolean flattened = isFlattened(base);
+      H handler = myHandler;
+      // If we already have the maximum number of handlers we can store in  
the
+      // flattened data structure, store the handlers in an external list
+      // instead.
+      if ((count == EXPECTED_HANDLERS) & flattened) {
+        unflatten(base);
+        flattened = false;
+      }
+      if (flattened) {
+        setFlatHandler(base, count, handler);
+      } else {
+        setHandler(base, count, handler);
+      }
+      setCount(base, count + 1);
+    }
+
+    public final <H extends EventHandler> void fireEvent(GwtEvent<H>  
event) {
+      Type<H> type = event.getAssociatedType();
+      int base = type.hashCode();
+      int count = getCount(base);
+      boolean isFlattened = isFlattened(base);
+      if (isFlattened) {
+        for (int i = 0; i < count; i++) {
+          // Gets the given handler to fire.
+          H handler = getFlatHandler(base, i);
+          // Fires the handler.
+          event.dispatch(handler);
+        }
+      } else {
+        JavaScriptObject handlers = getHandlers(base);
+        for (int i = 0; i < count; i++) {
+          // Gets the given handler to fire.
+
+          H handler = getHandler(handlers, i);
+
+          // Fires the handler.
+          event.dispatch(handler);
+        }
+      }
+    }
+
+    public final <H extends EventHandler> H getHandler(GwtEvent.Type<H>  
type,
+        int index) {
+      int base = type.hashCode();
+      int count = getCount(base);
+      if (index >= count) {
+        throw new IndexOutOfBoundsException("index: " + index);
+      }
+      return getHandler(base, index, isFlattened(base));
+    }
+
+    public final int getHandlerCount(GwtEvent.Type<?> eventKey) {
+      return getCount(eventKey.hashCode());
+    }
+
+    public final <H> void removeHandler(GwtEvent.Type<H> eventKey,
+        EventHandler handler) {
+      int base = eventKey.hashCode();
+
+      // Removing a handler is unusual, so smaller code is preferable to
+      // handling both flat and dangling list of pointers.
+      if (isFlattened(base)) {
+        unflatten(base);
+      }
+      boolean result = removeHelper(base, handler);
+      // Hiding this behind an assertion as we'd rather not force the  
compiler
+      // to have to include all handler.toString() instances.
+      assert result : handler + " did not exist";
+    }
+
+    private native int getCount(int index) /*-{
+      var count = this[index];
+      return count == null? 0:count;
+    }-*/;
+
+    private native <H extends EventHandler> H getFlatHandler(int base, int  
index) /*-{
+      return this[base + 2 + index];
+    }-*/;
+
+    private native <H extends EventHandler> H getHandler(int base, int  
index,
+        boolean flattened) /*-{
+      return flattened? this[base + 2 + index]: this[base + 1][index];
+    }-*/;
+
+    private native <H extends EventHandler> H getHandler(
+        JavaScriptObject handlers, int index) /*-{
+      return handlers[index];
+    }-*/;
+
+    private native JavaScriptObject getHandlers(int base) /*-{
+      return  this[base + 1];
+    }-*/;
+
+    private native boolean isFlattened(int base) /*-{
+      return this[base + 1] == null;
+    }-*/;
+
+    private native boolean removeHelper(int base, EventHandler handler)  
/*-{
+      // Find the handler.
+      var count = this[base];
+      var handlerList = this[base + 1];
+      var handlerIndex = -1;
+      for(var index = 0;  index < count; index++){
+        if(handlerList[index] == handler){
+          handlerIndex = index;
+          break;
+        }
+      }
+      if(handlerIndex == -1) {
+        return false;
+      }
+
+      // Remove the handler.
+      var last = count -1;
+      for(; handlerIndex < last; handlerIndex++){
+        handlerList[handlerIndex] = handlerList[handlerIndex+1]
+      }
+      handlerList[last] = null;
+      this[base] = this[base]-1;
+      return true;
+    }-*/;
+
+    private native void setCount(int index, int count) /*-{
+      this[index] = count;
+    }-*/;
+
+    private native void setFlatHandler(int base, int index, EventHandler  
handler) /*-{
+      this[base + 2 + index] = handler;
+    }-*/;
+
+    private native void setHandler(int base, int index, EventHandler  
handler) /*-{
+      this[base + 1][index] = handler;
+    }-*/;
+
+    private native void unflatten(int base) /*-{
+      var handlerList = {};
+      var count = this[base];
+      var start = base + 2;
+       for(var i = 0; i < count;i++){
+         handlerList[i] = this[start + i];
+         this[start + i] = null;
+        }
+       this[base + 1] = handlerList;
+    }-*/;
+  }
+
    // Used to optimize the JavaScript handler container structure.
    private static int EXPECTED_HANDLERS = 5;

-  private static final boolean useJs = false;
+  private static final boolean useJs = GWT.isClient();

    private static int index;

@@ -98,10 +272,9 @@
    }

    private int firingDepth = 0;
-  // Only JavaHandlerRegistry is supported for now as we need to decide if  
we
-  // need the more complicated js structure or not.
+  // Only one of JsHandlerRegistry and JavaHandlerRegistry are live at  
once.
+  private JsHandlerRegistry javaScriptRegistry;
    private JavaHandlerRegistry javaRegistry;
-  private JavaHandlerRegistry javaScriptRegistry;

    // source of the event.
    private final Object source;
@@ -116,7 +289,7 @@
     */
    public HandlerManager(Object source) {
      if (useJs) {
-      javaScriptRegistry = null;
+      javaScriptRegistry = JavaScriptObject.createObject().cast();
      } else {
        javaRegistry = new JavaHandlerRegistry();
      }

--~--~---------~--~----~------------~-------~--~----~
http://groups.google.com/group/Google-Web-Toolkit-Contributors
-~----------~----~----~----~------~----~------~--~---

Reply via email to