Revision: 7664
Author: b...@google.com
Date: Thu Mar  4 07:49:01 2010
Log: Created wiki page through web user interface.
http://code.google.com/p/google-web-toolkit/source/detail?r=7664

Added:
 /wiki/SoftPermutations.wiki

=======================================
--- /dev/null
+++ /wiki/SoftPermutations.wiki Thu Mar  4 07:49:01 2010
@@ -0,0 +1,69 @@
+#summary Runtime rebind evaluation (draft)
+
+= Introduction =
+
+Deferred-binding type replacement always requires a separate hard permutation. This contributes to permutation explosion. One technique for [ControllingPermutationExplosion controlling permutation explosion] is to allow certain rebind decisions to be evaluated at runtime thereby collapsing two or more hard permutations together.
+
+= Details =
+
+To address the common use-case of rendering-engine variants where using deferred-binding:
+{{{
+<!-- Define an adjunct property -->
+<define-property name="webkitVariant" values="none, safari, chrome, android, iphone" />
+<!-- Collapse all of its values -->
+<collapse-property name="webkitVariant" values="*" />
+<!-- Additional property provider to distinguish Chrome from Safari, etc... -->
+<property-provider name="webkitVariant">...</property-provider>
+
+<!-- Default value -->
+<set-property name="webkitVariant" value="none">
+  <none>
+    <when-property-is name="user.agent" value="safari" />
+  </none>
+</set-property>
+
+<!-- Regular rebind rules -->
+<replace-with name="com.google.ServiceImplAndroid">
+  <when-property-is name="webkitVariant" value="android" />
+  <when-type-is name="com.google.Service" />
+</replace-with>
+
+<!-- Generators are fine as well -->
+<generate-with name="com.google.ChromeServiceGenerator">
+  <when-property-is name="webkitVariant" value="chrome" />
+  <when-type-is name="com.google.Service" />
+</generate-with>
+}}}
+
+Instead of adding an extra `5 * N` factor to the number of hard permutations where `GWT.create(Service.class)` would be replaced with a `new ServiceImpl()`, the `GWT.create()` call is replaced with a call to a factory method, whose implementation looks like:
+
+{{{
+public static Object com_google_Service() {
+  switch (CollapsedPropertyHolder.permutationId$) {
+    case 0:
+      return new ServiceImplAndroid();
+    case 1:
+      return new ServiceImplChrome();
+  }
+  return new ServiceImplSafari();
+}
+}}}
+
+Even though there is a runtime aspect to the construction of a new `ServiceImpl` type, the virtual-permutation-specific method dispatch uses standard polymorphic dispatch to the implementation object and is subject to normal compiler optimizations. This continues to recommend the pattern of assigning the implementation type to a static, final field, e.g. `private static final Service = GWT.create(Service.class)`.
+
+= Virtual permutation id =
+
+The virtual permutation id is determined on module startup by examining the values returned by the deferred-biding property providers. Every value is assigned an arbitrary ordinal value. These ordinal values are then combined in a manner similar to computing an element memory offset in a multi-dimension array of known size. Given the following module definition snippet:
+{{{
+<collapse-property name="user.agent" value="safari, ie8" />
+<collapse-property name="locale" value="en_US, en_GB, en_AU" />
+<collapse-property name="foo" value="bar, baz" />
+}}}
+The virtual permutation would be computed as:
+{{{
+int user_agent = "safari".equals(user_agent_value) ? 1 : "ie8".equals(user_agent_value) ? 0 : die(); +int locale = "en_AU".equals(locale_value) ? 2 : "en_US".equals(locale_value) ? 1 : "en_GB".equals(locale_value) ? 0 : die(); +int foo = "bar".equals(foo_value) ? 1 : "baz".equals(foo_value) ? 0 : die();
+permutationId$ = user_agent * 1 + locale * 2 + foo * 6;
+}}}
+The multiplier sequence is [1], [user.agent], [user.agent + locale].

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

Reply via email to